conexus logo

miniterm.cpp

Conexus::TTY example reimplementing miniterm

/***************************************************************************
 *   Copyright (C) 2001 by Rick L. Vinyard, Jr.                            *
 *   rvinyard@cs.nmsu.edu                                                  *
 *                                                                         *
 *   This file is part of the conexus library.                             *
 *                                                                         *
 *   The conexus library is free software; you can redistribute it and/or  *
 *   modify it under the terms of the GNU General Public License version 3 *
 *   as published by the Free Software Foundation.                         *
 *                                                                         *
 *   The conexus library is distributed in the hope that it will be        *
 *   useful, but WITHOUT ANY WARRANTY; without even the implied warranty   *
 *   of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU   *
 *   General Public License for more details.                              *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this software. If not see <http://www.gnu.org/licenses/>.  *
 ***************************************************************************/

#include <conexus.h>
#include <iostream>


#include <termios.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/signal.h>
#include <stdlib.h>
#include <sys/wait.h>

#define BAUDRATE 4000000
#define ENDMINITERM 2 /* ctrl-b to quit miniterm */

#define _POSIX_SOURCE 1 /* POSIX compliant source */

using namespace std;

volatile bool STOP = false;

void child_handler( int s )
{
  STOP = true;
}

void print_data( const Conexus::Data d );

int main( int argc, char** argv )
{
  Conexus::init();

  int c;
  Conexus::TTY::pointer tty = Conexus::TTY::create();
  struct termios oldstdio, newstdio;
  struct sigaction sa;
  char default_device[] = "/dev/ttyS0";
  char* device = default_device;

  if ( argc == 2 )
    device = argv[ 1 ];

  /*
    Open modem device for reading and writing and not as controlling tty
    because we don't want to get killed if linenoise sends CTRL-C.
  */
  tty->open( device );

  tty->set_speed( BAUDRATE );

  /*
    Strange, but if you uncomment this command miniterm will not work
    even if you stop canonical mode for stdout.
  */
  tcgetattr( 1, &oldstdio );
  newstdio = tty->attributes();
  tcsetattr( 1, TCSANOW, &newstdio ); /* stdout settings like modem settings */

  /* terminal settings done, now handle in/ouput */
  switch ( fork() ) {
    case 0:  /* child */
      /* user input */
      close( 1 ); /* stdout not needed */
      for ( c = getchar(); c != ENDMINITERM ; c = getchar() )
        tty->write( &c, 1 );
      tty->close();
      tcsetattr( 1, TCSANOW, &oldstdio );
      exit( 0 ); /* will send a SIGCHLD to the parent */
      break;
    case - 1:
      perror( "fork" );
      tty->close();
      tcsetattr( 1, TCSANOW, &oldstdio );
      exit( -1 );
    default:  /* parent */
      close( 0 ); /* stdin not needed */
      sa.sa_handler = child_handler;
      sa.sa_flags = 0;
      sigaction( SIGCHLD, &sa, NULL ); /* handle dying child */
      tty->signal_data().connect( sigc::ptr_fun( &print_data ) );
      tty->start();
      while ( !STOP )
        ; /* modem input handler */
      tty->stop();
      wait( NULL ); /* wait for child to die or it will become a zombie */
      break;
  }
  return 0;
}

void print_data( const Conexus::Data d )
{
  for ( unsigned i = 0; i < d.size(); i++ )
    cout << ( char ) ( d.data() [ i ] );
  cout << flush;
}


Generated on Wed Jul 8 15:50:07 2009 for conexus by doxygen 1.5.8