play_again3.c 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. /* play_again3.c
  2. * purpose: ask if user wants another transaction
  3. * method: set tty into chr-by-chr, no-echo mode
  4. * set tty into no-delay mode
  5. * read char, return result
  6. * returns: 0=>yes, 1=>no, 2=>timeout
  7. * better: reset terminal mode on Interrupt
  8. */
  9. #include <stdio.h>
  10. #include <termios.h>
  11. #include <fcntl.h>
  12. #include <string.h>
  13. #define ASK "Do you want another transaction"
  14. #define TRIES 3 /* max tries */
  15. #define SLEEPTIME 2 /* time per try */
  16. #define BEEP putchar('\a') /* alert user */
  17. main()
  18. {
  19. int response;
  20. tty_mode(0); /* save current mode */
  21. set_cr_noecho_mode(); /* set -icanon, -echo */
  22. set_nodelay_mode(); /* noinput => EOF */
  23. response = get_response(ASK, TRIES); /* get some answer */
  24. tty_mode(1); /* restore orig mode */
  25. return response;
  26. }
  27. get_response( char *question , int maxtries)
  28. /*
  29. * purpose: ask a question and wait for a y/n answer or maxtries
  30. * method: use getchar and complain about non-y/n input
  31. * returns: 0=>yes, 1=>no, 2=>timeout
  32. */
  33. {
  34. int input;
  35. printf("%s (y/n)?", question); /* ask */
  36. fflush(stdout); /* force output */
  37. while ( 1 ){
  38. sleep(SLEEPTIME); /* wait a bit */
  39. input = tolower(get_ok_char()); /* get next chr */
  40. if ( input == 'y' )
  41. return 0;
  42. if ( input == 'n' )
  43. return 1;
  44. if ( maxtries-- == 0 ) /* outatime? */
  45. return 2; /* sayso */
  46. BEEP;
  47. }
  48. }
  49. /*
  50. * skip over non-legal chars and return y,Y,n,N or EOF
  51. */
  52. get_ok_char()
  53. {
  54. int c;
  55. while( ( c = getchar() ) != EOF && strchr("yYnN",c) == NULL )
  56. ;
  57. return c;
  58. }
  59. set_cr_noecho_mode()
  60. /*
  61. * purpose: put file descriptor 0 into chr-by-chr mode and noecho mode
  62. * method: use bits in termios
  63. */
  64. {
  65. struct termios ttystate;
  66. tcgetattr( 0, &ttystate); /* read curr. setting */
  67. ttystate.c_lflag &= ~ICANON; /* no buffering */
  68. ttystate.c_lflag &= ~ECHO; /* no echo either */
  69. ttystate.c_cc[VMIN] = 1; /* get 1 char at a time */
  70. tcsetattr( 0 , TCSANOW, &ttystate); /* install settings */
  71. }
  72. set_nodelay_mode()
  73. /*
  74. * purpose: put file descriptor 0 into no-delay mode
  75. * method: use fcntl to set bits
  76. * notes: tcsetattr() will do something similar, but it is complicated
  77. */
  78. {
  79. int termflags;
  80. termflags = fcntl(0, F_GETFL); /* read curr. settings */
  81. termflags |= O_NDELAY; /* flip on nodelay bit */
  82. fcntl(0, F_SETFL, termflags); /* and install 'em */
  83. }
  84. /* how == 0 => save current mode, how == 1 => restore mode */
  85. /* this version handles termios and fcntl flags */
  86. tty_mode(int how)
  87. {
  88. static struct termios original_mode;
  89. static int original_flags;
  90. if ( how == 0 ){
  91. tcgetattr(0, &original_mode);
  92. original_flags = fcntl(0, F_GETFL);
  93. }
  94. else {
  95. tcsetattr(0, TCSANOW, &original_mode);
  96. fcntl( 0, F_SETFL, original_flags);
  97. }
  98. }