English is suck. Real programmer speak some foreign language
- bjarne

Control over your terminal


Because of the frequent questions "How do I read one char at a time without waiting for a whole line?" and "How do I get a string from the user without echo of the input?" in irc channel #c I've decided to write something to point them to.

You often see answers like, "use curses", but that is the wrong answer most of the time. The library curses is for writing text GUIs, probably not what our aspiring programmer wants to do. Not just yet in her career anyway.

This simple problem demands a simple solution! And my prescription is the termios API!

The function prototypes resides in <termios.h>. The two functions we're interested in are these.

   int tcgetattr ( int fd, struct termios *termios_p );
       
   int tcsetattr ( int fd, int optional_actions, 
                   struct termios *termios_p );
Function tcgetattr() retrieves the current settings and tcsetattr() changes them, now isn't that intuitive? Now we just need to find out what is changed in the termios struct. If I remember correctly you shouldn't know or assume more of the struct than that it has these following entries. (Yes I'm a sloppy author not finding out about these things.)
              tcflag_t c_iflag;      /* input modes */
	      tcflag_t c_oflag;      /* output modes */
              tcflag_t c_cflag;      /* control modes */
              tcflag_t c_lflag;      /* local modes */
	      cc_t c_cc[NCCS];       /* control chars */
Even though both echo and line buffering is about input and output c_lflag is the entry to manipulate.

You're not supposed to remember all this and therefore you have the manpage available. The mask to allow echo is called ECHO and the mask for line-buffering is part of ICANON. So what we do is that we clear out these bits from c_lflag.

/* The amazing anykey program written by christian.sunesson@abc.se */

#include <termios.h>
#include <unistd.h>
#include <stdio.h>

int main()
{
   struct termios orig, changes;
   
   tcgetattr(STDIN_FILENO, &orig);
   
   changes = orig;
   changes.c_lflag &= ~(ICANON|ECHO);
   tcsetattr(STDIN_FILENO, TCSADRAIN, &changes);
   
   puts("Hit any key!");
   getchar();
   puts("Thanks!");
   
   /* restore old settings */
   tcsetattr(STDIN_FILENO, TCSADRAIN, &orig);
   return 0;
}

Klart!


Christian Sunesson - nossenus - christian.sunesson@abc.se - 1998 Oct.
Best viewed in lynx!

This page is Copyright © 1998 By C Scene. All Rights Reserved