C小程序 - 终端一些特性的控制

1079阅读 0评论2012-10-25 niannian
分类:C/C++


  1. #include    <stdio.h>
  2. #include    <termios.h>
  3. #include    <fcntl.h>
  4. #include    <string.h>

  5. #define    ASK        "Do you want again?"
  6. #define TIMEOUT 6 /* time per try */
  7. #define    BEEP putchar('\a') /* alert user */


  8. main()
  9. {
  10.     int    response;

  11.     tty_mode(0);                /* save current mode    */
  12.     set_input_mode(TIMEOUT);       
  13.     response = get_response(ASK);        /* get some answer    */
  14.     tty_mode(1);                /* restore orig mode    */
  15.     putchar('\n');
  16.     return response;
  17. }

  18. get_response( char *question )
  19. /*
  20.  * purpose: ask a question and wait for a y/n answer or maxtries
  21.  * method: use getchar and complain about non-y/n input
  22.  * returns: 0=>yes, 1=>no, 2=>timeout
  23.  */
  24. {
  25.     int    input;
  26. //后面采用了清空~ISIG标志位,所以这里就不用信号函数了
  27. //    signal(SIGINT, SIG_IGN);        /* ignore kbd signals    */
  28. //    signal(SIGQUIT, SIG_IGN);      
  29.     printf("%s (y/n)?", question);            /* ask        */
  30.     fflush(stdout);                    /* force output    */
  31.     while ( 1 ){
  32.         input = tolower(getchar()); /* get next chr */
  33.         if ( input == 'y' )
  34.             return 0;
  35.         if ( input == 'n' )
  36.             return 1;
  37.         if ( input == EOF )            /* timeout    */
  38.             return 2;            /* sayso    */
  39.         BEEP;
  40.     }
  41. }

  42. set_input_mode(int timeout)
  43. /*
  44.  * purpose: put file descriptor 0 into chr-by-chr mode and noecho mode
  45.  * AND set VTIME to 5*timeout
  46.  * See manpage for termios to learn how values of VMIN and
  47.  * VTIME work
  48.  * method: use bits in termios
  49.  */
  50. {
  51.     struct    termios    ttystate;

  52.     tcgetattr( 0, &ttystate);        /* read curr. setting    */
  53.     ttystate.c_lflag     &= ~ICANON;    /* 设置无缓冲,即输入一个字符就读一个字符,不会等到按回车再处理        */
  54.     ttystate.c_lflag     &= ~ECHO;    /* 设置不回显,即按下某个键,屏幕不会显示    */
  55.     ttystate.c_cc[VMIN]     = 1;        /* 最少读取的字符数    */
  56.     ttystate.c_cc[VTIME]     = 5*timeout;    /* 设置终端超时时间,这里是3秒,5*6=30毫秒,即3秒*/
  57.     ttystate.c_lflag     &= ~ISIG;    /* 不产生输入信号,即Ctrl+C这样的信号被屏蔽    */
  58.     tcsetattr( 0 , TCSANOW, &ttystate);    /* install settings    */
  59. }

  60. /* how == 0 => save current mode, how == 1 => restore mode */
  61. /* this version handles termios and fcntl flags */

  62. tty_mode(int how)
  63. {
  64.     static struct termios original_mode;
  65.     static int original_flags;
  66.     if ( how == 0 )
  67.         tcgetattr(0, &original_mode);
  68.     else
  69.         tcsetattr(0, TCSANOW, &original_mode);
  70. }
但是上面这个程序,却在超时后不会自动返回,主要是因为VMIN的设置有问题。

参看下面的解释:
转自
所以,在上述程序中把
ttystate.c_cc[VMIN]     = 1;        /* 最少读取的字符数    */
改为
ttystate.c_cc[VMIN]     = 0;        /* 最少读取的字符数    */

Then it works.
上一篇:C小程序 - fork理解
下一篇:getchar与getch