aaio2.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. /*
  2. * AAIO Advanced I/O
  3. * -----------------
  4. *
  5. * Many people moving from Windows programming to UNIX program have problems
  6. * with the missing non-blocking getch() and getche() functions provided by
  7. * conio.h. This library provides the functionality of getch(), getche() and
  8. * kbhit(). It does not require an initialization (like curses) and does
  9. * not abuse the terminal (i.e. whenever the mode of the terminal is
  10. * changed its state is stored so it can be restored). For increased
  11. * efficiency there exists funcionality to allow abuse of the terminal as well
  12. * as functions to restore or reset the terminal when the application exits.
  13. */
  14. /*
  15. -----BEGIN PGP SIGNED MESSAGE-----
  16. Hash: SHA1
  17. * Copyright (c) 2004-2005 by Daniel Aarno - <[email protected]>
  18. * M. Sc. Electrical Engineering * http://www.nada.kth.se/~bishop
  19. *
  20. * All Rights Reserved
  21. * ATTRIBUTION ASSURANCE LICENSE (adapted from the original BSD license)
  22. * Redistribution and use in source and binary forms, with or without
  23. * modification, are permitted provided that the conditions below are met.
  24. * These conditions require a modest attribution to (the
  25. * "Author"), who hopes that its promotional value may help justify the
  26. * thousands of dollars in otherwise billable time invested in writing
  27. * this and other freely available, open-source software.
  28. *
  29. * 1. Redistributions of source code, in whole or part and with or without
  30. * modification (the "Code"), must prominently display this GPG-signed
  31. * text in verifiable form.
  32. * 2. Redistributions of the Code in binary form must be accompanied by
  33. * this GPG-signed text in any documentation and, each time the resulting
  34. * executable program or a program dependent thereon is launched, a
  35. * prominent display (e.g., splash screen or banner text) of the Author's
  36. * attribution information, which includes:
  37. * (a) Name ("Daniel Aarno"),
  38. * (b) Professional identification ("M. Sc. Electrical Engineering"), and
  39. * (c) URL ("http://www.nada.kth.se/~bishop").
  40. * 3. Neither the name nor any trademark of the Author may be used to
  41. * endorse or promote products derived from this software without specific
  42. * prior written permission.
  43. * 4. Users are entirely responsible, to the exclusion of the Author and
  44. * any other persons, for compliance with (1) regulations set by owners or
  45. * administrators of employed equipment, (2) licensing terms of any other
  46. * software, and (3) local regulations regarding use, including those
  47. * regarding import, export, and use of encryption software.
  48. *
  49. * THIS FREE SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND
  50. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  51. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
  52. * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
  53. * EVENT SHALL THE AUTHOR OR ANY CONTRIBUTOR BE LIABLE FOR
  54. * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  55. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  56. * EFFECTS OF UNAUTHORIZED OR MALICIOUS NETWORK ACCESS;
  57. * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  58. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  59. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  60. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  61. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
  62. * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  63. -----BEGIN PGP SIGNATURE-----
  64. Version: GnuPG v1.2.4 (GNU/Linux)
  65. iD8DBQFCHuXui6ECThHTSIkRAk9qAKCVs7kMSUtv5YhljeQsAA52EcjTFgCeNflz
  66. w0lAUG3zeHQcJ+7t6tpce4s=
  67. =qlVs
  68. -----END PGP SIGNATURE-----
  69. */
  70. #include "aaio.h"
  71. #include <stdio.h>
  72. #include <stdlib.h>
  73. #include <errno.h>
  74. #include <unistd.h>
  75. #include <termios.h>
  76. #include <sys/ioctl.h>
  77. #ifdef HAVE_SYS_FILIO_H
  78. //needed on solaris to get FIONREAD
  79. #include <sys/filio.h>
  80. #endif
  81. #ifndef RESET_PATH
  82. #define RESET_PATH "/usr/bin/reset"
  83. #endif
  84. static const int NOECHO = 0;
  85. static void make_raw(struct termios *termios_p, int echo)
  86. {
  87. int e = echo == ECHO ? 0 : ECHO;
  88. termios_p->c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP
  89. |INLCR|IGNCR|ICRNL|IXON);
  90. termios_p->c_oflag &= ~OPOST;
  91. termios_p->c_lflag &= ~(ECHONL|ICANON|ISIG|IEXTEN|e);
  92. termios_p->c_cflag &= ~(CSIZE|PARENB);
  93. termios_p->c_cflag |= CS8;
  94. }
  95. static int set_stty_raw(struct termios *old, int echo)
  96. {
  97. struct termios nxt;
  98. //Store old terminal setting
  99. if(tcgetattr(STDIN_FILENO, old))
  100. return -1;
  101. //Create a raw terminal setting with "echo"
  102. nxt = *old;
  103. make_raw(&nxt, echo);
  104. //Set the termianal mode
  105. if(tcsetattr(STDIN_FILENO, 0, &nxt))
  106. return -1;
  107. return 0;
  108. }
  109. //======================================================================
  110. int getch(void)
  111. {
  112. struct termios old;
  113. int c;
  114. //set raw, no-echo mode
  115. if(set_stty_raw(&old, NOECHO))
  116. return -1;
  117. //read a char
  118. c = getchar();
  119. //Reset terminal to old mode
  120. if(tcsetattr(STDIN_FILENO, 0, &old))
  121. return -1;
  122. return c;
  123. }
  124. int getche(void)
  125. {
  126. struct termios old;
  127. int c;
  128. //set raw, echo mode
  129. if(set_stty_raw(&old, ECHO))
  130. return -1;
  131. //read a char
  132. c = getchar();
  133. //Reset terminal to old mode
  134. if(tcsetattr(STDIN_FILENO, 0, &old))
  135. return -1;
  136. return c;
  137. }
  138. int kbhit(void)
  139. {
  140. struct termios old;
  141. int i;
  142. //set raw, echo mode
  143. if(set_stty_raw(&old, NOECHO))
  144. return -1;
  145. //Get number of tokens
  146. if(-1 == ioctl(STDIN_FILENO, FIONREAD, &i)) {
  147. //Reset terminal to old mode
  148. tcsetattr(STDIN_FILENO, 0, &old);
  149. return -1;
  150. }
  151. //Reset terminal to old mode
  152. if(tcsetattr(STDIN_FILENO, 0, &old))
  153. return -1;
  154. return i;
  155. }
  156. int aaio_hard_reset(void)
  157. {
  158. if(system(RESET_PATH))
  159. return -1;
  160. return 0;
  161. }
  162. int aaio_reset(void)
  163. {
  164. return 0;
  165. }
  166. int aaio_grant_tty_lock(void)
  167. {
  168. return 0;
  169. }
  170. int aaio_flush(void)
  171. {
  172. int n = kbhit();
  173. int i;
  174. for(i = 0; i < n; i++)
  175. (void)getch();
  176. return n;
  177. }