Import of server, all hooked together
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
proto = userinput.proto
|
||||
source = parse.cpp parserstate.cpp parser.cpp templates.cpp terminal.cpp termemu.cpp parseraction.cpp terminalfunctions.cpp swrite.cpp terminalframebuffer.cpp terminaldispatcher.cpp terminaluserinput.cpp terminaldisplay.cpp network.cpp ntester.cpp ocb.cpp base64.cpp encrypt.cpp decrypt.cpp crypto.cpp networktransport.cpp networkinstruction.cpp user.cpp userinput.pb.cc completeterminal.cpp
|
||||
source = parse.cpp parserstate.cpp parser.cpp templates.cpp terminal.cpp termemu.cpp parseraction.cpp terminalfunctions.cpp swrite.cpp terminalframebuffer.cpp terminaldispatcher.cpp terminaluserinput.cpp terminaldisplay.cpp network.cpp ntester.cpp ocb.cpp base64.cpp encrypt.cpp decrypt.cpp crypto.cpp networktransport.cpp networkinstruction.cpp user.cpp userinput.pb.cc completeterminal.cpp rtm-server.cpp
|
||||
objects = parserstate.o parser.o templates.o terminal.o parseraction.o terminalfunctions.o swrite.o terminalframebuffer.o terminaldispatcher.o terminaluserinput.o terminaldisplay.o network.o ocb.o base64.o crypto.o networktransport.o networkinstruction.o user.o userinput.pb.o completeterminal.o
|
||||
repos = templates.rpo
|
||||
executables = parse termemu ntester encrypt decrypt
|
||||
executables = parse termemu ntester encrypt decrypt rtm-server
|
||||
|
||||
CXX = g++
|
||||
CXXFLAGS = -g --std=c++0x -pedantic -Werror -Wall -Wextra -Weffc++ -fno-implicit-templates -fno-default-inline -pipe -D_FILE_OFFSET_BITS=64 -D_XOPEN_SOURCE=500 -D_GNU_SOURCE -D_BSD_SOURCE
|
||||
@@ -26,6 +26,9 @@ encrypt: encrypt.o $(objects) ntester # serialize link steps because of -frepo
|
||||
decrypt: decrypt.o $(objects) encrypt # serialize link steps because of -frepo
|
||||
$(CXX) $(CXXFLAGS) -o $@ decrypt.o $(objects) $(LIBS)
|
||||
|
||||
rtm-server: rtm-server.o $(objects) decrypt # serialize link steps because of -frepo
|
||||
$(CXX) $(CXXFLAGS) -o $@ rtm-server.o $(objects) $(LIBS)
|
||||
|
||||
templates.o: templates.cpp
|
||||
$(CXX) $(CXXFLAGS) -frepo -c -o $@ $<
|
||||
|
||||
|
||||
+21
-2
@@ -2,8 +2,9 @@
|
||||
|
||||
using namespace std;
|
||||
using namespace Parser;
|
||||
using namespace Terminal;
|
||||
|
||||
string Terminal::Complete::act( const string &str )
|
||||
string Complete::act( const string &str )
|
||||
{
|
||||
for ( unsigned int i = 0; i < str.size(); i++ ) {
|
||||
/* parse octet into up to three actions */
|
||||
@@ -22,9 +23,27 @@ string Terminal::Complete::act( const string &str )
|
||||
return terminal.read_octets_to_host();
|
||||
}
|
||||
|
||||
string Terminal::Complete::act( const Action *act )
|
||||
string Complete::act( const Action *act )
|
||||
{
|
||||
/* apply action to terminal */
|
||||
act->act_on_terminal( &terminal );
|
||||
return terminal.read_octets_to_host();
|
||||
}
|
||||
|
||||
/* interface for Network::Transport */
|
||||
string Complete::diff_from( const Complete &existing )
|
||||
{
|
||||
return Terminal::Display::new_frame( true, existing.get_fb(), terminal.get_fb() );
|
||||
}
|
||||
|
||||
void Complete::apply_string( string diff )
|
||||
{
|
||||
string terminal_to_host = act( diff );
|
||||
assert( terminal_to_host.empty() );
|
||||
}
|
||||
|
||||
bool Complete::operator==( Complete const &x ) const
|
||||
{
|
||||
assert( parser == x.parser );
|
||||
return terminal == x.terminal;
|
||||
}
|
||||
|
||||
@@ -21,7 +21,13 @@ namespace Terminal {
|
||||
std::string open( void ) { return terminal.open(); }
|
||||
std::string close( void ) { return terminal.close(); }
|
||||
|
||||
const Framebuffer & get_fb( void ) { return terminal.get_fb(); }
|
||||
const Framebuffer & get_fb( void ) const { return terminal.get_fb(); }
|
||||
|
||||
/* interface for Network::Transport */
|
||||
void subtract( const Complete * ) {}
|
||||
std::string diff_from( const Complete &existing );
|
||||
void apply_string( std::string diff );
|
||||
bool operator==( const Complete &x ) const;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -149,7 +149,7 @@ void Transport<MyState, RemoteState>::update_assumed_receiver_state( void )
|
||||
template <class MyState, class RemoteState>
|
||||
void Transport<MyState, RemoteState>::rationalize_states( void )
|
||||
{
|
||||
MyState * const known_receiver_state = &sent_states.front().state;
|
||||
const MyState * known_receiver_state = &sent_states.front().state;
|
||||
|
||||
current_state.subtract( known_receiver_state );
|
||||
|
||||
@@ -257,7 +257,7 @@ string Transport<MyState, RemoteState>::get_remote_diff( void )
|
||||
|
||||
string ret( received_states.back().state.diff_from( last_receiver_state ) );
|
||||
|
||||
MyState * const oldest_receiver_state = &received_states.front().state;
|
||||
const RemoteState *oldest_receiver_state = &received_states.front().state;
|
||||
|
||||
for ( typename list< TimestampedState<RemoteState> >::reverse_iterator i = received_states.rbegin();
|
||||
i != received_states.rend();
|
||||
|
||||
@@ -105,7 +105,7 @@ namespace Network {
|
||||
|
||||
/* simple receiver */
|
||||
list< TimestampedState<RemoteState> > received_states;
|
||||
MyState last_receiver_state; /* the state we were in when user last queried state */
|
||||
RemoteState last_receiver_state; /* the state we were in when user last queried state */
|
||||
|
||||
FragmentAssembly fragments;
|
||||
|
||||
@@ -125,6 +125,7 @@ namespace Network {
|
||||
string get_key( void ) { return connection.get_key(); }
|
||||
|
||||
MyState &get_current_state( void ) { return current_state; }
|
||||
void set_current_state( const MyState &x ) { current_state = x; }
|
||||
|
||||
string get_remote_diff( void );
|
||||
|
||||
|
||||
+10
@@ -120,3 +120,13 @@ std::list<Parser::Action *> Parser::UTF8Parser::input( char c )
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
Parser::Parser::Parser( const Parser &other )
|
||||
: state( other.state )
|
||||
{}
|
||||
|
||||
Parser::Parser & Parser::Parser::operator=( const Parser &other )
|
||||
{
|
||||
state = other.state;
|
||||
return *this;
|
||||
}
|
||||
|
||||
+15
-4
@@ -18,19 +18,25 @@
|
||||
#endif
|
||||
|
||||
namespace Parser {
|
||||
static StateFamily family;
|
||||
|
||||
class Parser {
|
||||
private:
|
||||
StateFamily family;
|
||||
State *state;
|
||||
State const *state;
|
||||
|
||||
public:
|
||||
Parser() : family(), state( &family.s_Ground ) {}
|
||||
Parser() : state( &family.s_Ground ) {}
|
||||
|
||||
Parser( const Parser & );
|
||||
Parser( const Parser &other );
|
||||
Parser & operator=( const Parser & );
|
||||
~Parser() {}
|
||||
|
||||
std::list<Action *> input( wchar_t ch );
|
||||
|
||||
bool operator==( const Parser &x ) const
|
||||
{
|
||||
return state == x.state;
|
||||
}
|
||||
};
|
||||
|
||||
static const size_t BUF_SIZE = 8;
|
||||
@@ -46,6 +52,11 @@ namespace Parser {
|
||||
UTF8Parser();
|
||||
|
||||
std::list<Action *> input( char c );
|
||||
|
||||
bool operator==( const UTF8Parser &x ) const
|
||||
{
|
||||
return parser == x.parser;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
+23
-23
@@ -3,7 +3,7 @@
|
||||
|
||||
using namespace Parser;
|
||||
|
||||
Transition State::anywhere_rule( wchar_t ch )
|
||||
Transition State::anywhere_rule( wchar_t ch ) const
|
||||
{
|
||||
if ( (ch == 0x18) || (ch == 0x1A)
|
||||
|| ((0x80 <= ch) && (ch <= 0x8F))
|
||||
@@ -27,7 +27,7 @@ Transition State::anywhere_rule( wchar_t ch )
|
||||
return Transition( NULL, NULL ); /* don't allocate an Ignore action */
|
||||
}
|
||||
|
||||
Transition State::input( wchar_t ch )
|
||||
Transition State::input( wchar_t ch ) const
|
||||
{
|
||||
Transition ret = anywhere_rule( ch );
|
||||
if ( !ret.next_state ) {
|
||||
@@ -56,7 +56,7 @@ static bool GLGR ( wchar_t ch )
|
||||
|| ( (0xA0 <= ch) && (ch <= 0xFF) ) ); /* GR area */
|
||||
}
|
||||
|
||||
Transition Ground::input_state_rule( wchar_t ch )
|
||||
Transition Ground::input_state_rule( wchar_t ch ) const
|
||||
{
|
||||
if ( C0_prime( ch ) ) {
|
||||
return Transition( new Execute );
|
||||
@@ -69,12 +69,12 @@ Transition Ground::input_state_rule( wchar_t ch )
|
||||
return Transition();
|
||||
}
|
||||
|
||||
Action *Escape::enter( void )
|
||||
Action *Escape::enter( void ) const
|
||||
{
|
||||
return new Clear;
|
||||
}
|
||||
|
||||
Transition Escape::input_state_rule( wchar_t ch )
|
||||
Transition Escape::input_state_rule( wchar_t ch ) const
|
||||
{
|
||||
if ( C0_prime( ch ) ) {
|
||||
return Transition( new Execute );
|
||||
@@ -112,7 +112,7 @@ Transition Escape::input_state_rule( wchar_t ch )
|
||||
return Transition();
|
||||
}
|
||||
|
||||
Transition Escape_Intermediate::input_state_rule( wchar_t ch )
|
||||
Transition Escape_Intermediate::input_state_rule( wchar_t ch ) const
|
||||
{
|
||||
if ( C0_prime( ch ) ) {
|
||||
return Transition( new Execute );
|
||||
@@ -129,12 +129,12 @@ Transition Escape_Intermediate::input_state_rule( wchar_t ch )
|
||||
return Transition();
|
||||
}
|
||||
|
||||
Action *CSI_Entry::enter( void )
|
||||
Action *CSI_Entry::enter( void ) const
|
||||
{
|
||||
return new Clear;
|
||||
}
|
||||
|
||||
Transition CSI_Entry::input_state_rule( wchar_t ch )
|
||||
Transition CSI_Entry::input_state_rule( wchar_t ch ) const
|
||||
{
|
||||
if ( C0_prime( ch ) ) {
|
||||
return Transition( new Execute );
|
||||
@@ -164,7 +164,7 @@ Transition CSI_Entry::input_state_rule( wchar_t ch )
|
||||
return Transition();
|
||||
}
|
||||
|
||||
Transition CSI_Param::input_state_rule( wchar_t ch )
|
||||
Transition CSI_Param::input_state_rule( wchar_t ch ) const
|
||||
{
|
||||
if ( C0_prime( ch ) ) {
|
||||
return Transition( new Execute );
|
||||
@@ -189,7 +189,7 @@ Transition CSI_Param::input_state_rule( wchar_t ch )
|
||||
return Transition();
|
||||
}
|
||||
|
||||
Transition CSI_Intermediate::input_state_rule( wchar_t ch )
|
||||
Transition CSI_Intermediate::input_state_rule( wchar_t ch ) const
|
||||
{
|
||||
if ( C0_prime( ch ) ) {
|
||||
return Transition( new Execute );
|
||||
@@ -210,7 +210,7 @@ Transition CSI_Intermediate::input_state_rule( wchar_t ch )
|
||||
return Transition();
|
||||
}
|
||||
|
||||
Transition CSI_Ignore::input_state_rule( wchar_t ch )
|
||||
Transition CSI_Ignore::input_state_rule( wchar_t ch ) const
|
||||
{
|
||||
if ( C0_prime( ch ) ) {
|
||||
return Transition( new Execute );
|
||||
@@ -223,12 +223,12 @@ Transition CSI_Ignore::input_state_rule( wchar_t ch )
|
||||
return Transition();
|
||||
}
|
||||
|
||||
Action *DCS_Entry::enter( void )
|
||||
Action *DCS_Entry::enter( void ) const
|
||||
{
|
||||
return new Clear;
|
||||
}
|
||||
|
||||
Transition DCS_Entry::input_state_rule( wchar_t ch )
|
||||
Transition DCS_Entry::input_state_rule( wchar_t ch ) const
|
||||
{
|
||||
if ( (0x20 <= ch) && (ch <= 0x2F) ) {
|
||||
return Transition( new Collect, &family->s_DCS_Intermediate );
|
||||
@@ -253,7 +253,7 @@ Transition DCS_Entry::input_state_rule( wchar_t ch )
|
||||
return Transition();
|
||||
}
|
||||
|
||||
Transition DCS_Param::input_state_rule( wchar_t ch )
|
||||
Transition DCS_Param::input_state_rule( wchar_t ch ) const
|
||||
{
|
||||
if ( ( (0x30 <= ch) && (ch <= 0x39) ) || ( ch == 0x3B ) ) {
|
||||
return Transition( new Param );
|
||||
@@ -274,7 +274,7 @@ Transition DCS_Param::input_state_rule( wchar_t ch )
|
||||
return Transition();
|
||||
}
|
||||
|
||||
Transition DCS_Intermediate::input_state_rule( wchar_t ch )
|
||||
Transition DCS_Intermediate::input_state_rule( wchar_t ch ) const
|
||||
{
|
||||
if ( (0x20 <= ch) && (ch <= 0x2F) ) {
|
||||
return Transition( new Collect );
|
||||
@@ -291,17 +291,17 @@ Transition DCS_Intermediate::input_state_rule( wchar_t ch )
|
||||
return Transition();
|
||||
}
|
||||
|
||||
Action *DCS_Passthrough::enter( void )
|
||||
Action *DCS_Passthrough::enter( void ) const
|
||||
{
|
||||
return new Hook;
|
||||
}
|
||||
|
||||
Action *DCS_Passthrough::exit( void )
|
||||
Action *DCS_Passthrough::exit( void ) const
|
||||
{
|
||||
return new Unhook;
|
||||
}
|
||||
|
||||
Transition DCS_Passthrough::input_state_rule( wchar_t ch )
|
||||
Transition DCS_Passthrough::input_state_rule( wchar_t ch ) const
|
||||
{
|
||||
if ( C0_prime( ch ) || ( (0x20 <= ch) && (ch <= 0x7E) ) ) {
|
||||
return Transition( new Put );
|
||||
@@ -314,7 +314,7 @@ Transition DCS_Passthrough::input_state_rule( wchar_t ch )
|
||||
return Transition();
|
||||
}
|
||||
|
||||
Transition DCS_Ignore::input_state_rule( wchar_t ch )
|
||||
Transition DCS_Ignore::input_state_rule( wchar_t ch ) const
|
||||
{
|
||||
if ( ch == 0x9C ) {
|
||||
return Transition( &family->s_Ground );
|
||||
@@ -323,17 +323,17 @@ Transition DCS_Ignore::input_state_rule( wchar_t ch )
|
||||
return Transition();
|
||||
}
|
||||
|
||||
Action *OSC_String::enter( void )
|
||||
Action *OSC_String::enter( void ) const
|
||||
{
|
||||
return new OSC_Start;
|
||||
}
|
||||
|
||||
Action *OSC_String::exit( void )
|
||||
Action *OSC_String::exit( void ) const
|
||||
{
|
||||
return new OSC_End;
|
||||
}
|
||||
|
||||
Transition OSC_String::input_state_rule( wchar_t ch )
|
||||
Transition OSC_String::input_state_rule( wchar_t ch ) const
|
||||
{
|
||||
if ( (0x20 <= ch) && (ch <= 0x7F) ) {
|
||||
return Transition( new OSC_Put );
|
||||
@@ -346,7 +346,7 @@ Transition OSC_String::input_state_rule( wchar_t ch )
|
||||
return Transition();
|
||||
}
|
||||
|
||||
Transition SOS_PM_APC_String::input_state_rule( wchar_t ch )
|
||||
Transition SOS_PM_APC_String::input_state_rule( wchar_t ch ) const
|
||||
{
|
||||
if ( ch == 0x9C ) {
|
||||
return Transition( &family->s_Ground );
|
||||
|
||||
+26
-26
@@ -9,17 +9,17 @@ namespace Parser {
|
||||
class State
|
||||
{
|
||||
protected:
|
||||
virtual Transition input_state_rule( wchar_t ch ) = 0;
|
||||
virtual Transition input_state_rule( wchar_t ch ) const = 0;
|
||||
StateFamily *family;
|
||||
|
||||
private:
|
||||
Transition anywhere_rule( wchar_t ch );
|
||||
Transition anywhere_rule( wchar_t ch ) const;
|
||||
|
||||
public:
|
||||
void setfamily( StateFamily *s_family ) { family = s_family; }
|
||||
Transition input( wchar_t ch );
|
||||
virtual Action *enter( void ) { return new Ignore; }
|
||||
virtual Action *exit( void ) { return new Ignore; }
|
||||
Transition input( wchar_t ch ) const;
|
||||
virtual Action *enter( void ) const { return new Ignore; }
|
||||
virtual Action *exit( void ) const { return new Ignore; }
|
||||
|
||||
State() : family( NULL ) {};
|
||||
virtual ~State() {};
|
||||
@@ -29,58 +29,58 @@ namespace Parser {
|
||||
};
|
||||
|
||||
class Ground : public State {
|
||||
Transition input_state_rule( wchar_t ch );
|
||||
Transition input_state_rule( wchar_t ch ) const;
|
||||
};
|
||||
|
||||
class Escape : public State {
|
||||
Action *enter( void );
|
||||
Transition input_state_rule( wchar_t ch );
|
||||
Action *enter( void ) const;
|
||||
Transition input_state_rule( wchar_t ch ) const;
|
||||
};
|
||||
|
||||
class Escape_Intermediate : public State {
|
||||
Transition input_state_rule( wchar_t ch );
|
||||
Transition input_state_rule( wchar_t ch ) const;
|
||||
};
|
||||
|
||||
class CSI_Entry : public State {
|
||||
Action *enter( void );
|
||||
Transition input_state_rule( wchar_t ch );
|
||||
Action *enter( void ) const;
|
||||
Transition input_state_rule( wchar_t ch ) const;
|
||||
};
|
||||
class CSI_Param : public State {
|
||||
Transition input_state_rule( wchar_t ch );
|
||||
Transition input_state_rule( wchar_t ch ) const;
|
||||
};
|
||||
class CSI_Intermediate : public State {
|
||||
Transition input_state_rule( wchar_t ch );
|
||||
Transition input_state_rule( wchar_t ch ) const;
|
||||
};
|
||||
class CSI_Ignore : public State {
|
||||
Transition input_state_rule( wchar_t ch );
|
||||
Transition input_state_rule( wchar_t ch ) const;
|
||||
};
|
||||
|
||||
class DCS_Entry : public State {
|
||||
Action *enter( void );
|
||||
Transition input_state_rule( wchar_t ch );
|
||||
Action *enter( void ) const;
|
||||
Transition input_state_rule( wchar_t ch ) const;
|
||||
};
|
||||
class DCS_Param : public State {
|
||||
Transition input_state_rule( wchar_t ch );
|
||||
Transition input_state_rule( wchar_t ch ) const;
|
||||
};
|
||||
class DCS_Intermediate : public State {
|
||||
Transition input_state_rule( wchar_t ch );
|
||||
Transition input_state_rule( wchar_t ch ) const;
|
||||
};
|
||||
class DCS_Passthrough : public State {
|
||||
Action *enter( void );
|
||||
Transition input_state_rule( wchar_t ch );
|
||||
Action *exit( void );
|
||||
Action *enter( void ) const;
|
||||
Transition input_state_rule( wchar_t ch ) const;
|
||||
Action *exit( void ) const;
|
||||
};
|
||||
class DCS_Ignore : public State {
|
||||
Transition input_state_rule( wchar_t ch );
|
||||
Transition input_state_rule( wchar_t ch ) const;
|
||||
};
|
||||
|
||||
class OSC_String : public State {
|
||||
Action *enter( void );
|
||||
Transition input_state_rule( wchar_t ch );
|
||||
Action *exit( void );
|
||||
Action *enter( void ) const;
|
||||
Transition input_state_rule( wchar_t ch ) const;
|
||||
Action *exit( void ) const;
|
||||
};
|
||||
class SOS_PM_APC_String : public State {
|
||||
Transition input_state_rule( wchar_t ch );
|
||||
Transition input_state_rule( wchar_t ch ) const;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
+191
@@ -0,0 +1,191 @@
|
||||
#include <locale.h>
|
||||
#include <string.h>
|
||||
#include <langinfo.h>
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <pty.h>
|
||||
#include <stdlib.h>
|
||||
#include <poll.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/types.h>
|
||||
#include <pwd.h>
|
||||
|
||||
#include "networktransport.hpp"
|
||||
#include "completeterminal.hpp"
|
||||
#include "swrite.hpp"
|
||||
#include "user.hpp"
|
||||
|
||||
void serve( int host_fd );
|
||||
|
||||
using namespace std;
|
||||
|
||||
int main( void )
|
||||
{
|
||||
int master;
|
||||
struct termios child_termios;
|
||||
|
||||
/* Adopt implementation locale */
|
||||
if ( NULL == setlocale( LC_ALL, "" ) ) {
|
||||
perror( "setlocale" );
|
||||
exit( 1 );
|
||||
}
|
||||
|
||||
/* Verify locale calls for UTF-8 */
|
||||
if ( strcmp( nl_langinfo( CODESET ), "UTF-8" ) != 0 ) {
|
||||
fprintf( stderr, "stm requires a UTF-8 locale.\n" );
|
||||
exit( 1 );
|
||||
}
|
||||
|
||||
/* Verify terminal configuration */
|
||||
if ( tcgetattr( STDIN_FILENO, &child_termios ) < 0 ) {
|
||||
perror( "tcgetattr" );
|
||||
exit( 1 );
|
||||
}
|
||||
|
||||
if ( !(child_termios.c_iflag & IUTF8) ) {
|
||||
fprintf( stderr, "Warning: Locale is UTF-8 but termios IUTF8 flag not set. Setting IUTF8 flag.\n" );
|
||||
child_termios.c_iflag |= IUTF8;
|
||||
}
|
||||
|
||||
/* Fork child process */
|
||||
pid_t child = forkpty( &master, NULL, &child_termios, NULL );
|
||||
|
||||
if ( child == -1 ) {
|
||||
perror( "forkpty" );
|
||||
exit( 1 );
|
||||
}
|
||||
|
||||
if ( child == 0 ) {
|
||||
/* child */
|
||||
if ( setenv( "TERM", "xterm", true ) < 0 ) {
|
||||
perror( "setenv" );
|
||||
exit( 1 );
|
||||
}
|
||||
|
||||
/* ask ncurses to send UTF-8 instead of ISO 2022 for line-drawing chars */
|
||||
if ( setenv( "NCURSES_NO_UTF8_ACS", "1", true ) < 0 ) {
|
||||
perror( "setenv" );
|
||||
exit( 1 );
|
||||
}
|
||||
|
||||
/* get shell name */
|
||||
struct passwd *pw = getpwuid( geteuid() );
|
||||
if ( pw == NULL ) {
|
||||
perror( "getpwuid" );
|
||||
exit( 1 );
|
||||
}
|
||||
|
||||
char *my_argv[ 2 ];
|
||||
my_argv[ 0 ] = strdup( pw->pw_shell );
|
||||
assert( my_argv[ 0 ] );
|
||||
my_argv[ 1 ] = NULL;
|
||||
|
||||
if ( execve( pw->pw_shell, my_argv, environ ) < 0 ) {
|
||||
perror( "execve" );
|
||||
exit( 1 );
|
||||
}
|
||||
exit( 0 );
|
||||
} else {
|
||||
/* parent */
|
||||
serve( master );
|
||||
}
|
||||
|
||||
printf( "[stm is exiting.]\n" );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void serve( int host_fd )
|
||||
{
|
||||
/* get initial window size */
|
||||
struct winsize window_size;
|
||||
if ( ioctl( STDIN_FILENO, TIOCGWINSZ, &window_size ) < 0 ) {
|
||||
perror( "ioctl TIOCGWINSZ" );
|
||||
return;
|
||||
}
|
||||
|
||||
/* tell child process */
|
||||
if ( ioctl( host_fd, TIOCSWINSZ, &window_size ) < 0 ) {
|
||||
perror( "ioctl TIOCSWINSZ" );
|
||||
return;
|
||||
}
|
||||
|
||||
/* open parser and terminal */
|
||||
Terminal::Complete terminal( window_size.ws_col, window_size.ws_row );
|
||||
|
||||
/* open network */
|
||||
Network::UserStream blank;
|
||||
Network::Transport< Terminal::Complete, Network::UserStream > network( terminal, blank );
|
||||
|
||||
printf( "key= %s port= %d\n", network.get_key().c_str(), network.port() );
|
||||
|
||||
/* prepare to poll for events */
|
||||
struct pollfd pollfds[ 2 ];
|
||||
|
||||
pollfds[ 0 ].fd = network.fd();
|
||||
pollfds[ 0 ].events = POLLIN;
|
||||
|
||||
pollfds[ 1 ].fd = host_fd;
|
||||
pollfds[ 1 ].events = POLLIN;
|
||||
|
||||
uint64_t last_remote_num = network.get_remote_state_num();
|
||||
|
||||
while ( 1 ) {
|
||||
network.set_current_state( terminal );
|
||||
|
||||
int active_fds = poll( pollfds, 2, network.tick() );
|
||||
if ( active_fds < 0 ) {
|
||||
perror( "poll" );
|
||||
break;
|
||||
}
|
||||
|
||||
if ( pollfds[ 0 ].revents & POLLIN ) {
|
||||
/* packet received from the network */
|
||||
network.recv();
|
||||
|
||||
/* is new user input available for the terminal? */
|
||||
if ( network.get_remote_state_num() != last_remote_num ) {
|
||||
string terminal_to_host;
|
||||
|
||||
Network::UserStream us;
|
||||
us.apply_string( network.get_remote_diff() );
|
||||
/* apply userstream to terminal */
|
||||
for ( size_t i = 0; i < us.size(); i++ ) {
|
||||
terminal_to_host += terminal.act( us.get_action( i ) );
|
||||
}
|
||||
|
||||
/* write any writeback octets back to the host */
|
||||
if ( swrite( host_fd, terminal_to_host.c_str(), terminal_to_host.length() ) < 0 ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( pollfds[ 1 ].revents & POLLIN ) {
|
||||
/* input from the host needs to be fed to the terminal */
|
||||
const int buf_size = 16384;
|
||||
char buf[ buf_size ];
|
||||
|
||||
/* fill buffer if possible */
|
||||
ssize_t bytes_read = read( pollfds[ 1 ].fd, buf, buf_size );
|
||||
if ( bytes_read == 0 ) { /* EOF */
|
||||
return;
|
||||
} else if ( bytes_read < 0 ) {
|
||||
perror( "read" );
|
||||
return;
|
||||
}
|
||||
|
||||
/* write any writeback octets back to the host */
|
||||
string terminal_to_host = terminal.act( string( buf, bytes_read ) );
|
||||
if ( swrite( host_fd, terminal_to_host.c_str(), terminal_to_host.length() ) < 0 ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( (pollfds[ 0 ].revents | pollfds[ 1 ].revents)
|
||||
& (POLLERR | POLLHUP | POLLNVAL) ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <string>
|
||||
|
||||
#include "terminal.hpp"
|
||||
#include "completeterminal.hpp"
|
||||
|
||||
#include "user.hpp"
|
||||
#include "networktransport.cpp"
|
||||
@@ -29,5 +30,6 @@ template class vector<bool>;
|
||||
|
||||
template class vector<Instruction>;
|
||||
template class Transport<UserStream, UserStream>;
|
||||
template class Transport<Complete, UserStream>;
|
||||
|
||||
template class deque<UserEvent>;
|
||||
|
||||
@@ -28,7 +28,6 @@
|
||||
const size_t buf_size = 16384;
|
||||
|
||||
void emulate_terminal( int fd );
|
||||
int copy( int src, int dest );
|
||||
|
||||
int main( void )
|
||||
{
|
||||
|
||||
@@ -152,3 +152,10 @@ void Emulator::resize( size_t s_width, size_t s_height )
|
||||
{
|
||||
fb.resize( s_width, s_height );
|
||||
}
|
||||
|
||||
bool Emulator::operator==( Emulator const &x ) const
|
||||
{
|
||||
assert( dispatch == x.dispatch );
|
||||
assert( user == x.user );
|
||||
return fb == x.fb;
|
||||
}
|
||||
|
||||
+3
-1
@@ -49,7 +49,9 @@ namespace Terminal {
|
||||
std::string open( void ); /* put user cursor keys in application mode */
|
||||
std::string close( void ); /* restore user cursor keys */
|
||||
|
||||
const Framebuffer & get_fb( void ) { return fb; }
|
||||
const Framebuffer & get_fb( void ) const { return fb; }
|
||||
|
||||
bool operator==( Emulator const &x ) const;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -189,3 +189,9 @@ void Dispatcher::OSC_start( const Parser::OSC_Start *act )
|
||||
OSC_string.clear();
|
||||
act->handled = true;
|
||||
}
|
||||
|
||||
bool Dispatcher::operator==( const Dispatcher &x ) const
|
||||
{
|
||||
return ( params == x.params ) && ( parsed_params == x.parsed_params ) && ( parsed == x.parsed )
|
||||
&& ( dispatch_chars == x.dispatch_chars ) && ( OSC_string == x.OSC_string ) && ( terminal_to_host == x.terminal_to_host );
|
||||
}
|
||||
|
||||
@@ -76,6 +76,8 @@ namespace Terminal {
|
||||
void OSC_put( const Parser::OSC_Put *act );
|
||||
void OSC_start( const Parser::OSC_Start *act );
|
||||
void OSC_dispatch( const Parser::OSC_End *act, Framebuffer *fb );
|
||||
|
||||
bool operator==( const Dispatcher &x ) const;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -151,6 +151,12 @@ namespace Terminal {
|
||||
void resize( int s_width, int s_height );
|
||||
|
||||
DrawState( int s_width, int s_height );
|
||||
|
||||
bool operator==( const DrawState &x ) const
|
||||
{
|
||||
/* XXX other fields not necessary to compare -- for now */
|
||||
return ( width == x.width ) && ( height == x.height ) && ( renditions == x.renditions );
|
||||
}
|
||||
};
|
||||
|
||||
class Framebuffer {
|
||||
@@ -227,6 +233,11 @@ namespace Terminal {
|
||||
|
||||
void reset_cell( Cell *c ) { c->reset( ds.get_background_rendition() ); }
|
||||
void reset_row( Row *r ) { r->reset( ds.get_background_rendition() ); }
|
||||
|
||||
bool operator==( const Framebuffer &x ) const
|
||||
{
|
||||
return ( rows == x.rows ) && ( window_title == x.window_title ) && ( ds == x.ds );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,8 @@ namespace Terminal {
|
||||
|
||||
std::string input( const Parser::UserByte *act,
|
||||
bool application_mode_cursor_keys );
|
||||
|
||||
bool operator==( const UserInput &x ) const { return last_byte == x.last_byte; }
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -8,9 +8,9 @@ using namespace Parser;
|
||||
using namespace Network;
|
||||
using namespace ClientBuffers;
|
||||
|
||||
void UserStream::subtract( UserStream * const prefix )
|
||||
void UserStream::subtract( const UserStream *prefix )
|
||||
{
|
||||
for ( deque<UserEvent>::iterator i = prefix->actions.begin();
|
||||
for ( deque<UserEvent>::const_iterator i = prefix->actions.begin();
|
||||
i != prefix->actions.end();
|
||||
i++ ) {
|
||||
assert( !actions.empty() );
|
||||
@@ -19,7 +19,7 @@ void UserStream::subtract( UserStream * const prefix )
|
||||
}
|
||||
}
|
||||
|
||||
string UserStream::diff_from( UserStream const & existing )
|
||||
string UserStream::diff_from( const UserStream &existing )
|
||||
{
|
||||
deque<UserEvent>::iterator my_it = actions.begin();
|
||||
|
||||
@@ -83,3 +83,15 @@ void UserStream::apply_string( string diff )
|
||||
}
|
||||
}
|
||||
|
||||
const Parser::Action *UserStream::get_action( unsigned int i )
|
||||
{
|
||||
switch( actions[ i ].type ) {
|
||||
case UserByteType:
|
||||
return &( actions[ i ].userbyte );
|
||||
case ResizeType:
|
||||
return &( actions[ i ].resize );
|
||||
default:
|
||||
assert( false );
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,13 +40,14 @@ namespace Network {
|
||||
void push_back( Parser::UserByte s_userbyte ) { actions.push_back( UserEvent( s_userbyte ) ); }
|
||||
void push_back( Parser::Resize s_resize ) { actions.push_back( UserEvent( s_resize ) ); }
|
||||
|
||||
list<Parser::Action *> get_actions( void );
|
||||
size_t size( void ) { return actions.size(); }
|
||||
const Parser::Action *get_action( unsigned int i );
|
||||
|
||||
/* interface for Network::Transport */
|
||||
void subtract( UserStream * const prefix );
|
||||
string diff_from( UserStream const & existing );
|
||||
void subtract( const UserStream *prefix );
|
||||
string diff_from( const UserStream &existing );
|
||||
void apply_string( string diff );
|
||||
bool operator==( UserStream const &x ) const { return actions == x.actions; }
|
||||
bool operator==( const UserStream &x ) const { return actions == x.actions; }
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user