1
0

play_again4.c 3.2 KB

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