1 : /*
  2 : ** Copyright (C) 2000 Erik de Castro Lopo <erikd AT zip DOT com DOT au>
  3 : **  
  4 : ** This program is free software; you can redistribute it and/or modify
  5 : ** it under the terms of the GNU General Public License as published by
  6 : ** the Free Software Foundation; either version 2 of the License, or
  7 : ** (at your option) any later version.
  8 : ** 
  9 : ** This program is distributed in the hope that it will be useful,
 10 : ** but WITHOUT ANY WARRANTY; without even the implied warranty of
 11 : ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 12 : ** GNU General Public License for more details.
 13 : ** 
 14 : ** You should have received a copy of the GNU General Public License
 15 : ** along with this program; if not, write to the Free Software 
 16 : ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 17 : */
 18 : 
 19 : /* =========================================================================
 20 : ** This program actually provides the functionality which was advertised for
 21 : ** listing 13.6 of the book "SAMs Teach Yourself C for Linux Programming in
 22 : ** 21 days", by Erik de Castro Lopo, Brad Jones and Peter Aitken.
 23 : **
 24 : ** Compile this code using :
 25 : **
 26 : **     gcc -Wall list1306_readline.c -lreadline -o list1306_readline
 27 : **
 28 : ** On some systems it might be necessary to also link in the termcap
 29 : ** library as follows:
 30 : **
 31 : **     gcc -Wall list1306_readline.c -lreadline -ltermcap -o list1306_readline
 32 : **
 33 : ** If neither of these two compile commands works, you may be missing the
 34 : ** readline library or the header files for that library from your 
 35 : ** installation.
 36 : ** 
 37 : ** More information about the problem in the original code will appear on the
 38 : ** web page at http://www.zip.com.au/~erikd/BOOK/faq.html as soon as its
 39 : ** ready.
 40 : **
 41 : ** Dec 21 2000 : Version  1.0 <erikd AT zip DOT com DOT au>
 42 : ** Dec 21 2000 : Version  1.1 <erikd AT zip DOT com DOT au>
 43 : **                   Added atexit (), and restore_terminal ().
 44 : */
 45 : 
 46 : #include   <stdio.h>
 47 : #include   <stdlib.h>
 48 : #include   <unistd.h>
 49 : #include   <termios.h>
 50 : #include   <readline/readline.h>
 51 : 
 52 : #define    TERM_SILENCE_ON     1
 53 : #define    TERM_SILENCE_OFF    0
 54 : 
 55 : #define    TERM_STDIN          0
 56 : 
 57 : void silence_terminal (int on) ;
 58 : void restore_terminal (void) ;
 59 : 
 60 : int main (void)
 61 : {   int    age ;
 62 :     char   *name, *line ;
 63 :     
 64 :     /* During the running of this program we are fiddling with the terminal
 65 :     ** settings. If the program terminates before restoring the settings the
 66 :     ** settings will be permanent.
 67 :     ** To avoid this we register the restore_terminal function with atexit.
 68 :     ** The functions registered in this way are called when the program
 69 :     ** exits.
 70 :     */
 71 :     atexit (restore_terminal) ;
 72 :     
 73 :     line = readline ("Enter your age : ") ;
 74 :     sscanf (line, "%d", &age) ;
 75 : 
 76 :     /* While we're processing data (simulated by sleep (5) below) we want 
 77 :     ** to prevent the user from typing characters at the terminal.
 78 :     */
 79 :     silence_terminal (TERM_SILENCE_ON) ;
 80 :     
 81 :     printf ("Doing some processing here.\n") ;
 82 :     sleep (5) ; 
 83 : 
 84 :     /* We're now ready to resume dealing with the user, so turn the
 85 :     ** terminal back on.
 86 :     */    
 87 :     silence_terminal (TERM_SILENCE_OFF) ;
 88 :     name = readline ("Enter your name : ") ;
 89 : 
 90 :     /* Display the data. */
 91 :     printf("\nYour age is %d.\n", age);
 92 :     printf("Your name is %s.\n", name);
 93 : 
 94 :     return 0 ;
 95 : } /* main */
 96 : 
 97 : /* The atexit () function requires a parameter-less function so we
 98 : ** create one here which simply calls silence_terminal ().
 99 : */
100 : void restore_terminal (void)
101 : {    silence_terminal (TERM_SILENCE_OFF) ;
102 : } /* restore_terminal */
103 : 
104 : void silence_terminal (int on)
105 : {   /* On first entry to this function we want to store the current 
106 :     ** terminal settings so they can be restored later. We do that
107 :     ** by storing them in static structure. We also store a modified 
108 :     ** copy to use as the special terminal settings for a silent
109 :     ** terminal.
110 :     ** The terminal settings are stored in a termios structure 
111 :     ** defined in <termios.h>. They are declared static so they will
112 :     ** keep their information across function calls.
113 :     */
114 :     static struct termios original ;
115 :     static struct termios no_echo ;
116 :     static int    initialized = 0 ;
117 : 
118 : 
119 :     if (! initialized)
120 :     {   tcgetattr (TERM_STDIN, &original) ;
121 :         /* Also get a another ... */
122 :         tcgetattr (TERM_STDIN, &no_echo) ;
123 :         /* ... and modify it, turing of terminal charcter echoing. */
124 :         no_echo.c_lflag &= (~ECHO) ;
125 :         initialized = 1 ;
126 :         } ;
127 : 
128 :     if (on)
129 :     {   /* Turn off terminal character echoing. */
130 :         tcsetattr (TERM_STDIN, TCSANOW, &no_echo) ;
131 :         }
132 :     else
133 :     {   /* Restore original settings. */
134 :         tcsetattr (TERM_STDIN, TCSANOW, &original) ;
135 :         /* Flush the input buffer. */
136 :         tcflush (TERM_STDIN, TCIFLUSH) ;
137 :         } ;
138 : 
139 :     return ;
140 : } /* silence_terminal */