15. User Interfaces

Parsing Program Arguments

Testing Whether a Program Is Running Interactively

Clearing the Screen

Determining Terminal or Window Size

Changing Text Color

Reading from the Keyboard

Ringing the Terminal Bell

Using POSIX termios

Checking for Waiting Input

Reading Passwords

//------------------------------------------------------------------
// /!\ this function is deprecated
#include <unistd.h> // getpass()

...

char * password = getpass( "password : " );

...

//------------------------------------------------------------------
// gcc -Wall -o checkuser checkuser.c -lcrypt
#define _GNU_SOURCE

#include <stdio.h> // gnu version of getline()
#include <stdlib.h> // at_exit()
#include <string.h>
#include <unistd.h> // getlogin()
#include <termios.h> // struct termios, tcgetattr(), tcsetattr()
#include <pwd.h> // struct passwd, fgetpwent()
#include <crypt.h>  // crypt() 

static struct termios stored_settings;

void restore_term_setting( void ) {
  /*
    restore terminal setting
  */
  tcsetattr( 0, TCSANOW, &stored_settings);
}

int main( void ) {

  struct termios new_settings;
  char * cryptpw; // our encrypted password
  char * my_login = getlogin(); // our login

  /*
    we ask for password
  */
  fprintf( stdout, "Password : " );
  
  /*
    we disable echo input
  */
  
  // we first set an exit handler to restore terminal setting
  // * if something go wrong
  // * on the final return
  if( atexit( restore_term_setting ) != 0 ) {
    fprintf( stderr, "error on atexit\n" );
    exit(1);
  }

  
  tcgetattr( 0, &stored_settings ); // save terminal setting

  new_settings = stored_settings;
  new_settings.c_lflag &= (~ECHO); // disable echo input characters
  tcsetattr( 0, TCSANOW, &new_settings );

  /*
    we get the plain password
  */
  char * passwd = NULL;
  size_t size = 0;
  ssize_t ret;

  if( (ret = getline( &passwd, &size, stdin )) == -1 )
    exit(1);

  // we "chomp" the plain password
  char *p = strchr( passwd, '\n' );
  *p = 0;

  /*
    we get our login encrypted password
    /!\ most of the Linux system use shadow password
    we have to use /etc/shadow instead of /etc/passwd
    /!\ we have to be root in order to read /etc/shadow
  */
  FILE * fp;

  if( (fp = fopen( "/etc/shadow", "r" )) == NULL ) {
    perror("fopen");
    exit(1);
  }
  
  struct passwd * shadow_pwd_ent;
  cryptpw = NULL;
  
  while( (shadow_pwd_ent = fgetpwent(fp)) != NULL ) {
    // we search our login in the entry returned
    if( strcmp( my_login, shadow_pwd_ent->pw_name ) == 0 ) {
      cryptpw = shadow_pwd_ent->pw_passwd;
      break;
    }
  }

  fclose(fp);
    
  /*
    password matching
  */
  int match = strcmp( crypt(passwd, cryptpw), cryptpw );
    
  // we hurry to free the plain version of the password
  free(passwd), passwd = NULL;
  
  puts( "" );
  if( match == 0 )
    printf( "Welcome, %s\n", my_login );
  else 
    printf( "You are not %s\n", my_login );
  
  return 0;
}

Editing Input

Managing the Screen

Controlling Another Program with Expect

Creating Menus with Tk

Creating Dialog Boxes with Tk

Responding to Tk Resize Events

Removing the DOS Shell Window with Windows Perl/Tk

Program: Small termcap program

Program: tkshufflepod