linux终端控制和信号初步

linux终端控制和信号初步

讲解了终端的基本控制方法,通过五个例子一步一步完善,最终形成了完善的终端控制例程.

1.play_again0.c
功能:读入用户输入,输入y 返回0,输入n 返回1
 1  #include  < stdio.h >
 2  #include  < termios.h >
 3 
 4  #define QUESTION  " Do you want another transaction "
 5 
 6  int  get_response( char   * );
 7 
 8  int  main()
 9  {
10     int  response;
11    response  =  get_response(QUESTION);
12     if  (response  ==   0 )
13        printf( " the char you put is y\n " );
14     else
15      printf( " the char you put is n\n " );
16      
17     return  response;
18    
19  }
20 
21  int  get_response( char   * question)
22  {
23    printf( " %s (y/n)? " , question);
24     while ( 1 )
25    {
26       switch (getchar())
27      {
28         case   ' y ' :
29         case   ' Y ' return   0 ;
30         case   ' n ' :
31         case   ' N '
32         case  EOF: return   1 ;
33        
34      }
35    }
36  }
37 
缺陷: -用户输入y 和n 后必须回车才能使程序接收输入
      -输入非y 和n 的字符程序没有提示和处理

2, play_again1.c
功能:立即响应用户输入输入不合法,给出提示信息.

 1  /*
 2   * set tty into char -by char mode, read char, return result
 3   * response the input immediately
 4    */
 5  #include  < stdio.h >
 6  #include  < termios.h >
 7 
 8  #define QUESTION  " Do you want another transaction "
 9 
10  int  get_response( char   * );
11  void  tty_mode( int  );
12  void  set_crmode();
13 
14  int  main()
15  {
16     int  response;
17    tty_mode( 0 );
18    set_crmode();
19    response  =  get_response(QUESTION);
20     if  (response  ==   0 )
21        printf( " \n the char you put is y\n " );
22     else
23      printf( " \n the char you put is n\n " );
24    
25    tty_mode( 1 );
26     return  response;
27    
28  }
29 
30  int  get_response( char   * question)
31  {
32    printf( " %s (y/n)? " , question);
33     while ( 1 )
34    {
35       switch ( char  input  =  getchar())
36      {
37         case   ' y ' :
38         case   ' Y ' return   0 ;
39         case   ' n ' :
40         case   ' N '
41         case  EOF: return   1 ;
42         default :
43            printf( " \n cannot understatnd %c, " , input);
44            printf( " please type y or n \n " );
45        
46      }
47    }
48  }
49 
50  void  set_crmode()
51  /*
52   * put file descriptor 9 into char -by -char mode
53   * in common mode ,you can input 'stty -icanon' .
54    */
55  {
56    struct termios ttystate;
57    tcgetattr( 0 & ttystate);
58    ttystate.c_lflag   &=   ~ ICANON;
59    ttystate.c_cc[VMIN]  =   1 ;           // get 1 char at a time
60    tcsetattr( 0 , TCSANOW,  & ttystate);
61  }
62 
63  void  tty_mode( int  how)
64  {
65     static  struct termios original_mode;
66     if  (how == 0 )
67        tcgetattr( 0 & original_mode);
68     else
69        tcsetattr( 0 , TCSANOW,  & original_mode);
70        
71  }
72 

缺陷:每次给出提示,不友好,可以不显示用户输入

3,play_again2.c
功能:对于输入的字符不显示,当输入合法字符时正确返回
 1  /*
 2   * set tty into char -by char mode, read char, return result
 3   * response the input immediately
 4   * ingore non-y or non-n char
 5   * todo: timeout if user walks away
 6    */
 7  #include  < stdio.h >
 8  #include  < termios.h >
 9 
10  #define QUESTION  " Do you want another transaction "
11 
12  int  get_response( char   * );
13  void  tty_mode( int  );
14  void  set_crmode();
15 
16  int  main()
17  {
18     int  response;
19    tty_mode( 0 );
20    set_crmode();
21    response  =  get_response(QUESTION);
22     if  (response  ==   0 )
23        printf( " \n the char you put is y\n " );
24     else
25      printf( " \n the char you put is n\n " );
26    
27    tty_mode( 1 );
28     return  response;
29    
30  }
31 
32  int  get_response( char   * question)
33 
34     char   input;
35    printf( " %s (y/n)? " , question);
36     while ( 1 )
37    {
38       switch (input  =  getchar())
39      {
40         case   ' y ' :
41         case   ' Y ' return   0 ;
42         case   ' n ' :
43         case   ' N '
44         case  EOF: return   1 ;
45         // default:
46             // printf("\n cannot understatnd %c,", input);
47             // printf("please type y or n \n");
48          
49      }
50    }
51  }
52 
53  void  set_crmode()
54  /*
55   * put file descriptor 9 into char -by -char mode
56   * in common mode ,you can input 'stty -icanon' .
57    */
58  {
59    struct termios ttystate;
60    tcgetattr( 0 & ttystate);
61    ttystate.c_lflag   &=   ~ ICANON;      // no buffering
62    ttystate.c_lflag   &=   ~ ECHO;        //  no echo either
63    ttystate.c_cc[VMIN]  =   1 ;           // get 1 char at a time
64    tcsetattr( 0 , TCSANOW,  & ttystate);  // install settings
65  }
66 
67  void  tty_mode( int  how)
68  {
69     static  struct termios original_mode;
70     if  (how == 0 )
71        tcgetattr( 0 & original_mode);
72     else
73        tcsetattr( 0 , TCSANOW,  & original_mode);
74        
75  }
76 
缺陷:当用户什么都没有输入时,程序还在运行

4.play_again3.c
功能:用户不输入时,程序超时退出

  1  /*
  2   * set tty into char -by char mode, read char, return result
  3   * response the input immediately
  4   * ingore non-y or non-n char
  5   * add timeout machemism
  6   * todo: reset terminal mode on interrupt
  7    */
  8  #include  < stdio.h >
  9  #include  < unistd.h >
 10  #include  < termios.h >
 11  #include  < fcntl.h >
 12  #include  < string.h >
 13 
 14 
 15  #define QUESTION  " Do you want another transaction "
 16  #define TRIES  3
 17  #define SLEEPTIME  2
 18  #define BEEP putchar( ' \a ' )
 19 
 20  int  get_response( char   * );
 21  void  tty_mode( int  );
 22  void  set_crmode();
 23  void  set_nodelay_mode();    // timeout set
 24 
 25  int  main()
 26  {
 27    BEEP;
 28    
 29     int  response, maxtries;
 30    maxtries  =  TRIES;
 31    tty_mode( 0 );
 32    set_crmode();
 33    set_nodelay_mode();
 34    response  =  get_response(QUESTION);
 35     if  (response  ==   0 )
 36        printf( " \n the char you put is y\n " );
 37     else   if  (response  ==   1 )
 38      printf( " \n the char you put is n\n " );
 39     else   if  (response  ==   2 )
 40      printf( " \n timeout\n " );
 41    
 42    tty_mode( 1 );
 43     return  response;
 44    
 45  }
 46 
 47  char  get_ok_char()
 48  {
 49     int  c;
 50     while ( (c  =  getchar())  !=  EOF  &&  strchr( " yYNn " , c)  ==  NULL);
 51     return  c;
 52  }
 53  int  get_response( char   * question)
 54 
 55     char   input;
 56     int  maxtries  =  TRIES;
 57    printf( " %s (y/n)? " , question);
 58    fflush(stdout);
 59     while ( 1 )
 60    {
 61        sleep(SLEEPTIME);
 62         // input = tolower(get_ok_char());
 63        input  =  get_ok_char();
 64         if  (input  ==   ' y ' return   0 ;
 65         if  (input  ==   ' n ' return   1 ;
 66         if  (maxtries --   ==   0 return   2 ;
 67        
 68        BEEP;
 69      
 70    }
 71  }
 72 
 73  void  set_crmode()
 74  /*
 75   * put file descriptor 9 into char -by -char mode
 76   * in common mode ,you can input 'stty -icanon' .
 77    */
 78  {
 79    struct termios ttystate;
 80    tcgetattr( 0 & ttystate);
 81    ttystate.c_lflag   &=   ~ ICANON;      // no buffering
 82    ttystate.c_lflag   &=   ~ ECHO;        //  no echo either
 83    ttystate.c_cc[VMIN]  =   1 ;           // get 1 char at a time
 84    tcsetattr( 0 , TCSANOW,  & ttystate);  // install settings
 85  }
 86 
 87  void  tty_mode( int  how)
 88  {
 89     static  struct termios original_mode;
 90     static   int  original_flags;
 91     if  (how == 0 ){
 92        tcgetattr( 0 & original_mode);
 93        original_flags  =  fcntl( 0 , F_GETFL);
 94    }
 95     else
 96    {
 97        tcsetattr( 0 , TCSANOW,  & original_mode);
 98        fcntl( 0 , F_SETFL, original_flags);
 99    }
100        
101  }
102 
103  void  set_nodelay_mode()
104  /*
105   * put file descriptor 9 into no-0delay mode
106   * use fcntl to set bits
107   * notes: tcsetattr() will do something similar, but it is complicated
108    */
109  {
110     int  termflags;
111    termflags  =  fcntl( 0 , F_GETFL);   //  read curr. settings
112    termflags  |=  O_NDELAY;
113    fcntl( 0 , F_SETFL, termflags);
114  }
115 
缺陷:如果用户通过ctrl-c中止程序,系统不能恢复到原来的状态
5.play_again4.c
功能:加入了信号处理

  1  /*
  2   * set tty into char -by char mode, read char, return result
  3   * response the input immediately
  4   * ingore non-y or non-n char
  5   * add timeout machemism
  6   * add reset terminal mode on interrupt
  7   * ignore ctrl-C signal
  8    */
  9  #include  < stdio.h >
 10  #include  < unistd.h >
 11  #include  < termios.h >
 12  #include  < fcntl.h >
 13  #include  < string.h >
 14  #include  < signal.h >
 15 
 16  #define QUESTION  " Do you want another transaction "
 17  #define TRIES  3
 18  #define SLEEPTIME  2
 19  #define BEEP putchar( ' \a ' )
 20 
 21  int  get_response( char   * );
 22  void  tty_mode( int  );
 23  void  set_crmode();
 24  void  set_nodelay_mode();    // timeout set
 25  void  ctrl_c_handler( int  signum);
 26 
 27  int  main()
 28  {
 29    BEEP;
 30    
 31     int  response, maxtries;
 32    maxtries  =  TRIES;
 33    tty_mode( 0 );
 34    set_crmode();
 35    set_nodelay_mode();
 36    signal(SIGINT, ctrl_c_handler);
 37    signal(SIGQUIT, SIG_IGN);
 38    response  =  get_response(QUESTION);
 39     if  (response  ==   0 )
 40        printf( " \n the char you put is y\n " );
 41     else   if  (response  ==   1 )
 42      printf( " \n the char you put is n\n " );
 43     else   if  (response  ==   2 )
 44      printf( " \n timeout\n " );
 45    
 46    tty_mode( 1 );
 47     return  response;
 48    
 49  }
 50 
 51  char  get_ok_char()
 52  {
 53     int  c;
 54     while ( (c  =  getchar())  !=  EOF  &&  strchr( " yYNn " , c)  ==  NULL);
 55     return  c;
 56  }
 57  int  get_response( char   * question)
 58 
 59     char   input;
 60     int  maxtries  =  TRIES;
 61    printf( " %s (y/n)? " , question);
 62    fflush(stdout);
 63     while ( 1 )
 64    {
 65        sleep(SLEEPTIME);
 66         // input = tolower(get_ok_char());
 67        input  =  get_ok_char();
 68         if  (input  ==   ' y ' return   0 ;
 69         if  (input  ==   ' n ' return   1 ;
 70         if  (maxtries --   ==   0 return   2 ;
 71        
 72        BEEP;
 73      
 74    }
 75  }
 76 
 77  void  set_crmode()
 78  /*
 79   * put file descriptor 9 into char -by -char mode
 80   * in common mode ,you can input 'stty -icanon' .
 81    */
 82  {
 83    struct termios ttystate;
 84    tcgetattr( 0 & ttystate);
 85    ttystate.c_lflag   &=   ~ ICANON;      // no buffering
 86    ttystate.c_lflag   &=   ~ ECHO;        //  no echo either
 87    ttystate.c_cc[VMIN]  =   1 ;           // get 1 char at a time
 88    tcsetattr( 0 , TCSANOW,  & ttystate);  // install settings
 89  }
 90 
 91  void  tty_mode( int  how)
 92  {
 93     static  struct termios original_mode;
 94     static   int  original_flags;
 95     if  (how == 0 ){
 96        tcgetattr( 0 & original_mode);
 97        original_flags  =  fcntl( 0 , F_GETFL);
 98    }
 99     else
100    {
101        tcsetattr( 0 , TCSANOW,  & original_mode);
102        fcntl( 0 , F_SETFL, original_flags);
103    }
104        
105  }
106 
107  void  set_nodelay_mode()
108  /*
109   * put file descriptor 9 into no-0delay mode
110   * use fcntl to set bits
111   * notes: tcsetattr() will do something similar, but it is complicated
112    */
113  {
114     int  termflags;
115    termflags  =  fcntl( 0 , F_GETFL);   //  read curr. settings
116    termflags  |=  O_NDELAY;
117    fcntl( 0 , F_SETFL, termflags);
118  }
119  void  ctrl_c_handler( int  signum)
120  {
121     // called if SIGINT is detected and reset tty and scram
122    tty_mode( 1 );
123    exit( 1 );
124  }
125 

你可能感兴趣的:(linux终端控制和信号初步)