summaryrefslogtreecommitdiffstats
path: root/src/frontend/mosh-server.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/frontend/mosh-server.cc')
-rw-r--r--src/frontend/mosh-server.cc737
1 files changed, 369 insertions, 368 deletions
diff --git a/src/frontend/mosh-server.cc b/src/frontend/mosh-server.cc
index e258d1c..5d22553 100644
--- a/src/frontend/mosh-server.cc
+++ b/src/frontend/mosh-server.cc
@@ -81,14 +81,13 @@
#endif
#include "src/statesync/completeterminal.h"
-#include "src/util/swrite.h"
#include "src/statesync/user.h"
#include "src/util/fatal_assert.h"
#include "src/util/locale_utils.h"
#include "src/util/pty_compat.h"
#include "src/util/select.h"
+#include "src/util/swrite.h"
#include "src/util/timestamp.h"
-#include "src/util/fatal_assert.h"
#ifndef _PATH_BSHELL
#define _PATH_BSHELL "/bin/sh"
@@ -100,34 +99,40 @@ using ServerConnection = Network::Transport<Terminal::Complete, Network::UserStr
static void serve( int host_fd,
int pipe_fd,
- Terminal::Complete &terminal,
- ServerConnection &network,
- long network_timeout,
- long network_signaled_timeout );
-
-static int run_server( const char *desired_ip, const char *desired_port,
- const std::string &command_path, char *command_argv[],
- const int colors, unsigned int verbose, bool with_motd );
-
-
-static void print_version( FILE *file )
+ Terminal::Complete& terminal,
+ ServerConnection& network,
+ long network_timeout,
+ long network_signaled_timeout );
+
+static int run_server( const char* desired_ip,
+ const char* desired_port,
+ const std::string& command_path,
+ char* command_argv[],
+ const int colors,
+ unsigned int verbose,
+ bool with_motd );
+
+static void print_version( FILE* file )
{
fputs( "mosh-server (" PACKAGE_STRING ") [build " BUILD_VERSION "]\n"
- "Copyright 2012 Keith Winstein <mosh-devel@mit.edu>\n"
- "License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.\n"
- "This is free software: you are free to change and redistribute it.\n"
- "There is NO WARRANTY, to the extent permitted by law.\n", file );
+ "Copyright 2012 Keith Winstein <mosh-devel@mit.edu>\n"
+ "License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.\n"
+ "This is free software: you are free to change and redistribute it.\n"
+ "There is NO WARRANTY, to the extent permitted by law.\n",
+ file );
}
-static void print_usage( FILE *stream, const char *argv0 )
+static void print_usage( FILE* stream, const char* argv0 )
{
- fprintf( stream, "Usage: %s new [-s] [-v] [-i LOCALADDR] [-p PORT[:PORT2]] [-c COLORS] [-l NAME=VALUE] [-- COMMAND...]\n", argv0 );
+ fprintf( stream,
+ "Usage: %s new [-s] [-v] [-i LOCALADDR] [-p PORT[:PORT2]] [-c COLORS] [-l NAME=VALUE] [-- COMMAND...]\n",
+ argv0 );
}
-static bool print_motd( const char *filename );
+static bool print_motd( const char* filename );
static void chdir_homedir( void );
static bool motd_hushed( void );
-static void warn_unattached( const std::string & ignore_entry );
+static void warn_unattached( const std::string& ignore_entry );
/* Simple spinloop */
static void spin( void )
@@ -146,7 +151,7 @@ static void spin( void )
static std::string get_SSH_IP( void )
{
- const char *SSH_CONNECTION = getenv( "SSH_CONNECTION" );
+ const char* SSH_CONNECTION = getenv( "SSH_CONNECTION" );
if ( !SSH_CONNECTION ) { /* Older sshds don't set this */
fputs( "Warning: SSH_CONNECTION not found; binding to any interface.\n", stderr );
return std::string( "" );
@@ -170,7 +175,7 @@ static std::string get_SSH_IP( void )
return local_interface_IP;
}
-int main( int argc, char *argv[] )
+int main( int argc, char* argv[] )
{
/* For security, make sure we don't dump core */
Crypto::disable_dumping_core();
@@ -178,11 +183,11 @@ int main( int argc, char *argv[] )
/* Detect edge case */
fatal_assert( argc > 0 );
- const char *desired_ip = NULL;
+ const char* desired_ip = NULL;
std::string desired_ip_str;
- const char *desired_port = NULL;
+ const char* desired_port = NULL;
std::string command_path;
- char **command_argv = NULL;
+ char** command_argv = NULL;
int colors = 0;
unsigned int verbose = 0; /* don't close stdin/stdout/stderr */
/* Will cause mosh-server not to correctly detach on old versions of sshd. */
@@ -190,17 +195,17 @@ int main( int argc, char *argv[] )
/* strip off command */
for ( int i = 1; i < argc; i++ ) {
- if ( 0 == strcmp( argv[ i ], "--help" ) || 0 == strcmp( argv[ i ], "-h" ) ) {
- print_usage( stdout, argv[ 0 ] );
+ if ( 0 == strcmp( argv[i], "--help" ) || 0 == strcmp( argv[i], "-h" ) ) {
+ print_usage( stdout, argv[0] );
exit( 0 );
}
- if ( 0 == strcmp( argv[ i ], "--version" ) ) {
+ if ( 0 == strcmp( argv[i], "--version" ) ) {
print_version( stdout );
exit( 0 );
}
- if ( 0 == strcmp( argv[ i ], "--" ) ) { /* -- is mandatory */
+ if ( 0 == strcmp( argv[i], "--" ) ) { /* -- is mandatory */
if ( i != argc - 1 ) {
- command_argv = argv + i + 1;
+ command_argv = argv + i + 1;
}
argc = i; /* rest of options before -- */
break;
@@ -208,95 +213,94 @@ int main( int argc, char *argv[] )
}
/* Parse new command-line syntax */
- if ( (argc >= 2)
- && (strcmp( argv[ 1 ], "new" ) == 0) ) {
+ if ( ( argc >= 2 ) && ( strcmp( argv[1], "new" ) == 0 ) ) {
/* new option syntax */
int opt;
- while ( (opt = getopt( argc - 1, argv + 1, "@:i:p:c:svl:" )) != -1 ) {
+ while ( ( opt = getopt( argc - 1, argv + 1, "@:i:p:c:svl:" ) ) != -1 ) {
switch ( opt ) {
- /*
- * This undocumented option does nothing but eat its argument.
- * Useful in scripting where you prepend something to a
- * mosh-server argv, and might end up with something like
- * "mosh-server new -v new -c 256", now you can say
- * "mosh-server new -v -@ new -c 256" to discard the second
- * "new".
- */
- case '@':
- break;
- case 'i':
- desired_ip = optarg;
- break;
- case 'p':
- desired_port = optarg;
- break;
- case 's':
- desired_ip = NULL;
- desired_ip_str = get_SSH_IP();
- if ( !desired_ip_str.empty() ) {
- desired_ip = desired_ip_str.c_str();
- fatal_assert( desired_ip );
- }
- break;
- case 'c':
- try {
- colors = myatoi( optarg );
- } catch ( const CryptoException & ) {
- fprintf( stderr, "%s: Bad number of colors (%s)\n", argv[ 0 ], optarg );
- print_usage( stderr, argv[ 0 ] );
- exit( 1 );
- }
- break;
- case 'v':
- verbose++;
- break;
- case 'l':
- locale_vars.push_back( std::string( optarg ) );
- break;
- default:
- /* don't die on unknown options */
- print_usage( stderr, argv[ 0 ] );
- break;
+ /*
+ * This undocumented option does nothing but eat its argument.
+ * Useful in scripting where you prepend something to a
+ * mosh-server argv, and might end up with something like
+ * "mosh-server new -v new -c 256", now you can say
+ * "mosh-server new -v -@ new -c 256" to discard the second
+ * "new".
+ */
+ case '@':
+ break;
+ case 'i':
+ desired_ip = optarg;
+ break;
+ case 'p':
+ desired_port = optarg;
+ break;
+ case 's':
+ desired_ip = NULL;
+ desired_ip_str = get_SSH_IP();
+ if ( !desired_ip_str.empty() ) {
+ desired_ip = desired_ip_str.c_str();
+ fatal_assert( desired_ip );
+ }
+ break;
+ case 'c':
+ try {
+ colors = myatoi( optarg );
+ } catch ( const CryptoException& ) {
+ fprintf( stderr, "%s: Bad number of colors (%s)\n", argv[0], optarg );
+ print_usage( stderr, argv[0] );
+ exit( 1 );
+ }
+ break;
+ case 'v':
+ verbose++;
+ break;
+ case 'l':
+ locale_vars.push_back( std::string( optarg ) );
+ break;
+ default:
+ /* don't die on unknown options */
+ print_usage( stderr, argv[0] );
+ break;
}
}
} else if ( argc == 1 ) {
/* legacy argument parsing for older client wrapper script */
/* do nothing */
} else if ( argc == 2 ) {
- desired_ip = argv[ 1 ];
+ desired_ip = argv[1];
} else if ( argc == 3 ) {
- desired_ip = argv[ 1 ];
- desired_port = argv[ 2 ];
+ desired_ip = argv[1];
+ desired_port = argv[2];
} else {
- print_usage( stderr, argv[ 0 ] );
+ print_usage( stderr, argv[0] );
exit( 1 );
}
/* Sanity-check arguments */
int dpl, dph;
- if ( desired_port && ! Connection::parse_portrange( desired_port, dpl, dph ) ) {
- fprintf( stderr, "%s: Bad UDP port range (%s)\n", argv[ 0 ], desired_port );
- print_usage( stderr, argv[ 0 ] );
+ if ( desired_port && !Connection::parse_portrange( desired_port, dpl, dph ) ) {
+ fprintf( stderr, "%s: Bad UDP port range (%s)\n", argv[0], desired_port );
+ print_usage( stderr, argv[0] );
exit( 1 );
}
bool with_motd = false;
- #ifdef HAVE_SYSLOG
- openlog(argv[0], LOG_PID | LOG_NDELAY, LOG_AUTH);
- #endif
+#ifdef HAVE_SYSLOG
+ openlog( argv[0], LOG_PID | LOG_NDELAY, LOG_AUTH );
+#endif
/* Get shell */
- char *my_argv[ 2 ];
+ char* my_argv[2];
std::string shell_name;
if ( !command_argv ) {
/* get shell name */
- const char *shell = getenv( "SHELL" );
+ const char* shell = getenv( "SHELL" );
if ( shell == NULL ) {
- struct passwd *pw = getpwuid( getuid() );
+ struct passwd* pw = getpwuid( getuid() );
if ( pw == NULL ) {
- perror( "getpwuid" );
- exit( 1 );
+ perror( "getpwuid" );
+ exit( 1 );
}
shell = pw->pw_shell;
}
@@ -308,18 +312,18 @@ int main( int argc, char *argv[] )
command_path = shell_path;
- size_t shell_slash( shell_path.rfind('/') );
+ size_t shell_slash( shell_path.rfind( '/' ) );
if ( shell_slash == std::string::npos ) {
shell_name = shell_path;
} else {
- shell_name = shell_path.substr(shell_slash + 1);
+ shell_name = shell_path.substr( shell_slash + 1 );
}
/* prepend '-' to make login shell */
shell_name = '-' + shell_name;
- my_argv[ 0 ] = const_cast<char *>( shell_name.c_str() );
- my_argv[ 1 ] = NULL;
+ my_argv[0] = const_cast<char*>( shell_name.c_str() );
+ my_argv[1] = NULL;
command_argv = my_argv;
with_motd = true;
@@ -338,13 +342,11 @@ int main( int argc, char *argv[] )
/* apply locale-related environment variables from client */
clear_locale_variables();
- for ( std::list<std::string>::const_iterator i = locale_vars.begin();
- i != locale_vars.end();
- i++ ) {
- char *env_string = strdup( i->c_str() );
+ for ( std::list<std::string>::const_iterator i = locale_vars.begin(); i != locale_vars.end(); i++ ) {
+ char* env_string = strdup( i->c_str() );
fatal_assert( env_string );
if ( 0 != putenv( env_string ) ) {
- perror( "putenv" );
+ perror( "putenv" );
}
}
@@ -354,39 +356,46 @@ int main( int argc, char *argv[] )
LocaleVar client_ctype = get_ctype();
std::string client_charset( locale_charset() );
- fprintf( stderr, "mosh-server needs a UTF-8 native locale to run.\n\n"
- "Unfortunately, the local environment (%s) specifies\n"
- "the character set \"%s\",\n\n"
- "The client-supplied environment (%s) specifies\n"
- "the character set \"%s\".\n\n",
- native_ctype.str().c_str(), native_charset.c_str(), client_ctype.str().c_str(), client_charset.c_str() );
- int unused __attribute((unused)) = system( "locale" );
+ fprintf( stderr,
+ "mosh-server needs a UTF-8 native locale to run.\n\n"
+ "Unfortunately, the local environment (%s) specifies\n"
+ "the character set \"%s\",\n\n"
+ "The client-supplied environment (%s) specifies\n"
+ "the character set \"%s\".\n\n",
+ native_ctype.str().c_str(),
+ native_charset.c_str(),
+ client_ctype.str().c_str(),
+ client_charset.c_str() );
+ int unused __attribute( ( unused ) ) = system( "locale" );
exit( 1 );
}
}
try {
return run_server( desired_ip, desired_port, command_path, command_argv, colors, verbose, with_motd );
- } catch ( const Network::NetworkException &e ) {
- fprintf( stderr, "Network exception: %s\n",
- e.what() );
+ } catch ( const Network::NetworkException& e ) {
+ fprintf( stderr, "Network exception: %s\n", e.what() );
return 1;
- } catch ( const Crypto::CryptoException &e ) {
- fprintf( stderr, "Crypto exception: %s\n",
- e.what() );
+ } catch ( const Crypto::CryptoException& e ) {
+ fprintf( stderr, "Crypto exception: %s\n", e.what() );
return 1;
}
}
-static int run_server( const char *desired_ip, const char *desired_port,
- const std::string &command_path, char *command_argv[],
- const int colors, unsigned int verbose, bool with_motd ) {
+static int run_server( const char* desired_ip,
+ const char* desired_port,
+ const std::string& command_path,
+ char* command_argv[],
+ const int colors,
+ unsigned int verbose,
+ bool with_motd )
+{
/* get network idle timeout */
long network_timeout = 0;
- char *timeout_envar = getenv( "MOSH_SERVER_NETWORK_TMOUT" );
+ char* timeout_envar = getenv( "MOSH_SERVER_NETWORK_TMOUT" );
if ( timeout_envar && *timeout_envar ) {
errno = 0;
- char *endptr;
+ char* endptr;
network_timeout = strtol( timeout_envar, &endptr, 10 );
if ( *endptr != '\0' || ( network_timeout == 0 && errno == EINVAL ) ) {
fputs( "MOSH_SERVER_NETWORK_TMOUT not a valid integer, ignoring\n", stderr );
@@ -397,10 +406,10 @@ static int run_server( const char *desired_ip, const char *desired_port,
}
/* get network signaled idle timeout */
long network_signaled_timeout = 0;
- char *signal_envar = getenv( "MOSH_SERVER_SIGNAL_TMOUT" );
+ char* signal_envar = getenv( "MOSH_SERVER_SIGNAL_TMOUT" );
if ( signal_envar && *signal_envar ) {
errno = 0;
- char *endptr;
+ char* endptr;
network_signaled_timeout = strtol( signal_envar, &endptr, 10 );
if ( *endptr != '\0' || ( network_signaled_timeout == 0 && errno == EINVAL ) ) {
fputs( "MOSH_SERVER_SIGNAL_TMOUT not a valid integer, ignoring\n", stderr );
@@ -411,9 +420,7 @@ static int run_server( const char *desired_ip, const char *desired_port,
}
/* get initial window size */
struct winsize window_size;
- if ( ioctl( STDIN_FILENO, TIOCGWINSZ, &window_size ) < 0 ||
- window_size.ws_col == 0 ||
- window_size.ws_row == 0 ) {
+ if ( ioctl( STDIN_FILENO, TIOCGWINSZ, &window_size ) < 0 || window_size.ws_col == 0 || window_size.ws_row == 0 ) {
/* Fill in sensible defaults. */
/* They will be overwritten by client on first connection. */
memset( &window_size, 0, sizeof( window_size ) );
@@ -450,7 +457,6 @@ static int run_server( const char *desired_ip, const char *desired_port,
fatal_assert( 0 == sigaction( SIGHUP, &sa, NULL ) );
fatal_assert( 0 == sigaction( SIGPIPE, &sa, NULL ) );
-
/* detach from terminal */
fflush( NULL );
pid_t the_pid = fork();
@@ -458,16 +464,18 @@ static int run_server( const char *desired_ip, const char *desired_port,
perror( "fork" );
} else if ( the_pid > 0 ) {
fputs( "\nmosh-server (" PACKAGE_STRING ") [build " BUILD_VERSION "]\n"
- "Copyright 2012 Keith Winstein <mosh-devel@mit.edu>\n"
- "License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.\n"
- "This is free software: you are free to change and redistribute it.\n"
- "There is NO WARRANTY, to the extent permitted by law.\n\n", stderr );
+ "Copyright 2012 Keith Winstein <mosh-devel@mit.edu>\n"
+ "License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.\n"
+ "This is free software: you are free to change and redistribute it.\n"
+ "There is NO WARRANTY, to the extent permitted by law.\n\n",
+ stderr );
- fprintf( stderr, "[mosh-server detached, pid = %d]\n", static_cast<int>(the_pid) );
+ fprintf( stderr, "[mosh-server detached, pid = %d]\n", static_cast<int>( the_pid ) );
#ifndef HAVE_IUTF8
fputs( "\nWarning: termios IUTF8 flag not defined.\n"
- "Character-erase of multibyte character sequence\n"
- "probably does not work properly on this platform.\n", stderr );
+ "Character-erase of multibyte character sequence\n"
+ "probably does not work properly on this platform.\n",
+ stderr );
#endif /* HAVE_IUTF8 */
fflush( NULL );
@@ -493,9 +501,8 @@ static int run_server( const char *desired_ip, const char *desired_port,
exit( 1 );
}
- if ( dup2 ( nullfd, STDIN_FILENO ) < 0 ||
- dup2 ( nullfd, STDOUT_FILENO ) < 0 ||
- dup2 ( nullfd, STDERR_FILENO ) < 0 ) {
+ if ( dup2( nullfd, STDIN_FILENO ) < 0 || dup2( nullfd, STDOUT_FILENO ) < 0
+ || dup2( nullfd, STDERR_FILENO ) < 0 ) {
perror( "dup2" );
exit( 1 );
}
@@ -506,13 +513,13 @@ static int run_server( const char *desired_ip, const char *desired_port,
}
}
- char utmp_entry[ 64 ] = { 0 };
+ char utmp_entry[64] = { 0 };
snprintf( utmp_entry, 64, "mosh [%ld]", static_cast<long int>( getpid() ) );
/* Fork child process */
int pipes[2];
- int success = pipe(pipes);
- if (success == -1) {
+ int success = pipe( pipes );
+ if ( success == -1 ) {
perror( "pipe" );
exit( 1 );
}
@@ -538,9 +545,9 @@ static int run_server( const char *desired_ip, const char *desired_port,
fatal_assert( 0 == sigaction( SIGHUP, &sa, NULL ) );
fatal_assert( 0 == sigaction( SIGPIPE, &sa, NULL ) );
- #ifdef HAVE_SYSLOG
+#ifdef HAVE_SYSLOG
closelog();
- #endif
+#endif
/* close server-related file descriptors */
network.reset();
@@ -565,7 +572,7 @@ static int run_server( const char *desired_ip, const char *desired_port,
const char default_term[] = "xterm";
const char color_term[] = "xterm-256color";
- if ( setenv( "TERM", (colors == 256) ? color_term : default_term, true ) < 0 ) {
+ if ( setenv( "TERM", ( colors == 256 ) ? color_term : default_term, true ) < 0 ) {
perror( "setenv" );
exit( 1 );
}
@@ -584,7 +591,7 @@ static int run_server( const char *desired_ip, const char *desired_port,
chdir_homedir();
- if ( with_motd && (!motd_hushed()) ) {
+ if ( with_motd && ( !motd_hushed() ) ) {
// On illumos motd is printed by /etc/profile.
#ifndef __sun
// For Ubuntu, try and print one of {,/var}/run/motd.dynamic.
@@ -593,11 +600,11 @@ static int run_server( const char *desired_ip, const char *desired_port,
// this always happens.
// XXX Hackish knowledge of Ubuntu PAM configuration.
// But this seems less awful than build-time detection with autoconf.
- if (!print_motd("/run/motd.dynamic")) {
- print_motd("/var/run/motd.dynamic");
+ if ( !print_motd( "/run/motd.dynamic" ) ) {
+ print_motd( "/var/run/motd.dynamic" );
}
// Always print traditional /etc/motd.
- print_motd("/etc/motd");
+ print_motd( "/etc/motd" );
#endif
warn_unattached( utmp_entry );
}
@@ -607,9 +614,9 @@ static int run_server( const char *desired_ip, const char *desired_port,
// -1, errno == EINTR -- retry
// otherwise, give up
while ( read( pipes[0], linebuf, sizeof( linebuf ) ) == -1 ) {
- if ( errno != EINTR ) {
- err( 1, "parent signal" );
- }
+ if ( errno != EINTR ) {
+ err( 1, "parent signal" );
+ }
}
Crypto::reenable_dumping_core();
@@ -621,20 +628,20 @@ static int run_server( const char *desired_ip, const char *desired_port,
}
if ( close( pipes[0] ) < 0 ) {
- perror( "child read pipe close" );
- exit( 1 );
+ perror( "child read pipe close" );
+ exit( 1 );
}
} else {
- /* parent */
- if ( close(pipes[0]) < 0 ) {
- perror( "parent read pipe close" );
- exit( 1 );
- }
+ /* parent */
+ if ( close( pipes[0] ) < 0 ) {
+ perror( "parent read pipe close" );
+ exit( 1 );
+ }
/* Drop unnecessary privileges */
#ifdef HAVE_PLEDGE
/* OpenBSD pledge() syscall */
- if ( pledge( "stdio inet tty", NULL )) {
+ if ( pledge( "stdio inet tty", NULL ) ) {
perror( "pledge() failed" );
exit( 1 );
}
@@ -647,17 +654,15 @@ static int run_server( const char *desired_ip, const char *desired_port,
try {
serve( master, pipes[1], terminal, *network, network_timeout, network_signaled_timeout );
- } catch ( const Network::NetworkException &e ) {
- fprintf( stderr, "Network exception: %s\n",
- e.what() );
- } catch ( const Crypto::CryptoException &e ) {
- fprintf( stderr, "Crypto exception: %s\n",
- e.what() );
+ } catch ( const Network::NetworkException& e ) {
+ fprintf( stderr, "Network exception: %s\n", e.what() );
+ } catch ( const Crypto::CryptoException& e ) {
+ fprintf( stderr, "Crypto exception: %s\n", e.what() );
}
- #ifdef HAVE_UTEMPTER
+#ifdef HAVE_UTEMPTER
utempter_remove_record( master );
- #endif
+#endif
if ( close( master ) < 0 ) {
perror( "close" );
@@ -670,35 +675,40 @@ static int run_server( const char *desired_ip, const char *desired_port,
return 0;
}
-static void serve( int host_fd, int pipe_fd, Terminal::Complete &terminal, ServerConnection &network, long network_timeout, long network_signaled_timeout )
+static void serve( int host_fd,
+ int pipe_fd,
+ Terminal::Complete& terminal,
+ ServerConnection& network,
+ long network_timeout,
+ long network_signaled_timeout )
{
/* scale timeouts */
const uint64_t network_timeout_ms = static_cast<uint64_t>( network_timeout ) * 1000;
const uint64_t network_signaled_timeout_ms = static_cast<uint64_t>( network_signaled_timeout ) * 1000;
/* prepare to poll for events */
- Select &sel = Select::get_instance();
+ Select& sel = Select::get_instance();
sel.add_signal( SIGTERM );
sel.add_signal( SIGINT );
sel.add_signal( SIGUSR1 );
uint64_t last_remote_num = network.get_remote_state_num();
- #ifdef HAVE_UTEMPTER
+#ifdef HAVE_UTEMPTER
bool connected_utmp = false;
- #endif
- #if defined(HAVE_SYSLOG) || defined(HAVE_UTEMPTER)
+#endif
+#if defined( HAVE_SYSLOG ) || defined( HAVE_UTEMPTER )
bool force_connection_change_evt = false;
Addr saved_addr;
socklen_t saved_addr_len = 0;
- #endif
+#endif
- #ifdef HAVE_SYSLOG
- struct passwd *pw = getpwuid( getuid() );
- if (pw == NULL) {
+#ifdef HAVE_SYSLOG
+ struct passwd* pw = getpwuid( getuid() );
+ if ( pw == NULL ) {
throw NetworkException( std::string( "serve: getpwuid: " ) + strerror( errno ), 0 );
}
- syslog(LOG_INFO, "user %s session begin", pw->pw_name);
- #endif
+ syslog( LOG_INFO, "user %s session begin", pw->pw_name );
+#endif
bool child_released = false;
@@ -710,8 +720,7 @@ static void serve( int host_fd, int pipe_fd, Terminal::Complete &terminal, Serve
timeout = std::min( timeout, network.wait_time() );
timeout = std::min( timeout, terminal.wait_time( now ) );
- if ( (!network.get_remote_state_num())
- || network.shutdown_in_progress() ) {
+ if ( ( !network.get_remote_state_num() ) || network.shutdown_in_progress() ) {
timeout = std::min( timeout, 5000 );
}
/*
@@ -719,31 +728,30 @@ static void serve( int host_fd, int pipe_fd, Terminal::Complete &terminal, Serve
* We may want to wake up sooner.
*/
if ( network_timeout_ms ) {
- int64_t network_sleep = network_timeout_ms -
- ( now - network.get_latest_remote_state().timestamp );
- if ( network_sleep < 0 ) {
- network_sleep = 0;
- } else if ( network_sleep > INT_MAX ) {
- /* 24 days might be too soon. That's OK. */
- network_sleep = INT_MAX;
- }
- timeout = std::min( timeout, static_cast<int>(network_sleep) );
+ int64_t network_sleep = network_timeout_ms - ( now - network.get_latest_remote_state().timestamp );
+ if ( network_sleep < 0 ) {
+ network_sleep = 0;
+ } else if ( network_sleep > INT_MAX ) {
+ /* 24 days might be too soon. That's OK. */
+ network_sleep = INT_MAX;
+ }
+ timeout = std::min( timeout, static_cast<int>( network_sleep ) );
}
/* poll for events */
sel.clear_fds();
- std::vector< int > fd_list( network.fds() );
+ std::vector<int> fd_list( network.fds() );
assert( fd_list.size() == 1 ); /* servers don't hop */
int network_fd = fd_list.back();
sel.add_fd( network_fd );
if ( !network.shutdown_in_progress() ) {
- sel.add_fd( host_fd );
+ sel.add_fd( host_fd );
}
int active_fds = sel.select( timeout );
if ( active_fds < 0 ) {
- perror( "select" );
- break;
+ perror( "select" );
+ break;
}
now = Network::timestamp();
@@ -751,203 +759,199 @@ static void serve( int host_fd, int pipe_fd, Terminal::Complete &terminal, Serve
std::string terminal_to_host;
if ( sel.read( network_fd ) ) {
- /* packet received from the network */
- network.recv();
-
- /* is new user input available for the terminal? */
- if ( network.get_remote_state_num() != last_remote_num ) {
- last_remote_num = network.get_remote_state_num();
-
-
- Network::UserStream us;
- us.apply_string( network.get_remote_diff() );
- /* apply userstream to terminal */
- for ( size_t i = 0; i < us.size(); i++ ) {
- const Parser::Action &action = us.get_action( i );
- if ( typeid( action ) == typeid( Parser::Resize ) ) {
- /* apply only the last consecutive Resize action */
- if ( i < us.size() - 1 ) {
- const Parser::Action &next = us.get_action( i + 1 );
- if ( typeid( next ) == typeid( Parser::Resize ) ) {
- continue;
- }
- }
- /* tell child process of resize */
- const Parser::Resize &res = static_cast<const Parser::Resize &>( action );
- struct winsize window_size;
- if ( ioctl( host_fd, TIOCGWINSZ, &window_size ) < 0 ) {
- perror( "ioctl TIOCGWINSZ" );
- network.start_shutdown();
- }
- window_size.ws_col = res.width;
- window_size.ws_row = res.height;
- if ( ioctl( host_fd, TIOCSWINSZ, &window_size ) < 0 ) {
- perror( "ioctl TIOCSWINSZ" );
- network.start_shutdown();
- }
- }
- terminal_to_host += terminal.act( action );
- }
-
- if ( !us.empty() ) {
- /* register input frame number for future echo ack */
- terminal.register_input_frame( last_remote_num, now );
- }
-
- /* update client with new state of terminal */
- if ( !network.shutdown_in_progress() ) {
- network.set_current_state( terminal );
- }
- #if defined(HAVE_SYSLOG) || defined(HAVE_UTEMPTER)
- #ifdef HAVE_UTEMPTER
- if (!connected_utmp) {
- force_connection_change_evt = true;
- } else {
- force_connection_change_evt = false;
- }
- #else
- force_connection_change_evt = false;
- #endif
-
- /**
- * - HAVE_UTEMPTER - update utmp entry if we have become "connected"
- * - HAVE_SYSLOG - log connection information to syslog
- **/
- if ( (force_connection_change_evt)
- || saved_addr_len != network.get_remote_addr_len()
- || memcmp( &saved_addr, &network.get_remote_addr(),
- saved_addr_len ) != 0 ) {
-
- saved_addr = network.get_remote_addr();
- saved_addr_len = network.get_remote_addr_len();
-
- char host[ NI_MAXHOST ];
- int errcode = getnameinfo( &saved_addr.sa, saved_addr_len,
- host, sizeof( host ), NULL, 0,
- NI_NUMERICHOST );
- if ( errcode != 0 ) {
- throw NetworkException( std::string( "serve: getnameinfo: " ) + gai_strerror( errcode ), 0 );
- }
-
- #ifdef HAVE_UTEMPTER
- utempter_remove_record( host_fd );
- char tmp[ 64 + NI_MAXHOST ];
- snprintf( tmp, 64 + NI_MAXHOST, "%s via mosh [%ld]", host, static_cast<long int>( getpid() ) );
- utempter_add_record( host_fd, tmp );
-
- connected_utmp = true;
- #endif
-
- #ifdef HAVE_SYSLOG
- syslog(LOG_INFO, "user %s connected from host: %s", pw->pw_name, host);
- #endif
- }
- #endif
-
- /* Tell child to start login session. */
- if ( !child_released ) {
- if ( close( pipe_fd ) < 0 ) {
- err( 1, "child release" );
- }
- child_released = true;
- }
- }
+ /* packet received from the network */
+ network.recv();
+
+ /* is new user input available for the terminal? */
+ if ( network.get_remote_state_num() != last_remote_num ) {
+ last_remote_num = network.get_remote_state_num();
+
+ Network::UserStream us;
+ us.apply_string( network.get_remote_diff() );
+ /* apply userstream to terminal */
+ for ( size_t i = 0; i < us.size(); i++ ) {
+ const Parser::Action& action = us.get_action( i );
+ if ( typeid( action ) == typeid( Parser::Resize ) ) {
+ /* apply only the last consecutive Resize action */
+ if ( i < us.size() - 1 ) {
+ const Parser::Action& next = us.get_action( i + 1 );
+ if ( typeid( next ) == typeid( Parser::Resize ) ) {
+ continue;
+ }
+ }
+ /* tell child process of resize */
+ const Parser::Resize& res = static_cast<const Parser::Resize&>( action );
+ struct winsize window_size;
+ if ( ioctl( host_fd, TIOCGWINSZ, &window_size ) < 0 ) {
+ perror( "ioctl TIOCGWINSZ" );
+ network.start_shutdown();
+ }
+ window_size.ws_col = res.width;
+ window_size.ws_row = res.height;
+ if ( ioctl( host_fd, TIOCSWINSZ, &window_size ) < 0 ) {
+ perror( "ioctl TIOCSWINSZ" );
+ network.start_shutdown();
+ }
+ }
+ terminal_to_host += terminal.act( action );
+ }
+
+ if ( !us.empty() ) {
+ /* register input frame number for future echo ack */
+ terminal.register_input_frame( last_remote_num, now );
+ }
+
+ /* update client with new state of terminal */
+ if ( !network.shutdown_in_progress() ) {
+ network.set_current_state( terminal );
+ }
+#if defined( HAVE_SYSLOG ) || defined( HAVE_UTEMPTER )
+#ifdef HAVE_UTEMPTER
+ if ( !connected_utmp ) {
+ force_connection_change_evt = true;
+ } else {
+ force_connection_change_evt = false;
+ }
+#else
+ force_connection_change_evt = false;
+#endif
+
+ /**
+ * - HAVE_UTEMPTER - update utmp entry if we have become "connected"
+ * - HAVE_SYSLOG - log connection information to syslog
+ **/
+ if ( ( force_connection_change_evt ) || saved_addr_len != network.get_remote_addr_len()
+ || memcmp( &saved_addr, &network.get_remote_addr(), saved_addr_len ) != 0 ) {
+
+ saved_addr = network.get_remote_addr();
+ saved_addr_len = network.get_remote_addr_len();
+
+ char host[NI_MAXHOST];
+ int errcode
+ = getnameinfo( &saved_addr.sa, saved_addr_len, host, sizeof( host ), NULL, 0, NI_NUMERICHOST );
+ if ( errcode != 0 ) {
+ throw NetworkException( std::string( "serve: getnameinfo: " ) + gai_strerror( errcode ), 0 );
+ }
+
+#ifdef HAVE_UTEMPTER
+ utempter_remove_record( host_fd );
+ char tmp[64 + NI_MAXHOST];
+ snprintf( tmp, 64 + NI_MAXHOST, "%s via mosh [%ld]", host, static_cast<long int>( getpid() ) );
+ utempter_add_record( host_fd, tmp );
+
+ connected_utmp = true;
+#endif
+
+#ifdef HAVE_SYSLOG
+ syslog( LOG_INFO, "user %s connected from host: %s", pw->pw_name, host );
+#endif
+ }
+#endif
+
+ /* Tell child to start login session. */
+ if ( !child_released ) {
+ if ( close( pipe_fd ) < 0 ) {
+ err( 1, "child release" );
+ }
+ child_released = true;
+ }
+ }
}
-
- if ( (!network.shutdown_in_progress()) && sel.read( host_fd ) ) {
- /* 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( host_fd, buf, buf_size );
+
+ if ( ( !network.shutdown_in_progress() ) && sel.read( host_fd ) ) {
+ /* 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( host_fd, buf, buf_size );
/* If the pty slave is closed, reading from the master can fail with
EIO (see #264). So we treat errors on read() like EOF. */
if ( bytes_read <= 0 ) {
- network.start_shutdown();
- } else {
- terminal_to_host += terminal.act( std::string( buf, bytes_read ) );
-
- /* update client with new state of terminal */
- network.set_current_state( terminal );
- }
+ network.start_shutdown();
+ } else {
+ terminal_to_host += terminal.act( std::string( buf, bytes_read ) );
+
+ /* update client with new state of terminal */
+ network.set_current_state( terminal );
+ }
}
/* write user input and terminal writeback to the host */
if ( swrite( host_fd, terminal_to_host.c_str(), terminal_to_host.length() ) < 0 ) {
- network.start_shutdown();
+ network.start_shutdown();
}
bool idle_shutdown = false;
- if ( network_timeout_ms &&
- network_timeout_ms <= time_since_remote_state ) {
- idle_shutdown = true;
- fprintf( stderr, "Network idle for %llu seconds.\n",
- static_cast<unsigned long long>( time_since_remote_state / 1000 ) );
+ if ( network_timeout_ms && network_timeout_ms <= time_since_remote_state ) {
+ idle_shutdown = true;
+ fprintf( stderr,
+ "Network idle for %llu seconds.\n",
+ static_cast<unsigned long long>( time_since_remote_state / 1000 ) );
}
if ( sel.signal( SIGUSR1 )
- && ( !network_signaled_timeout_ms || network_signaled_timeout_ms <= time_since_remote_state ) ) {
- idle_shutdown = true;
- fprintf( stderr, "Network idle for %llu seconds when SIGUSR1 received\n",
- static_cast<unsigned long long>( time_since_remote_state / 1000 ) );
+ && ( !network_signaled_timeout_ms || network_signaled_timeout_ms <= time_since_remote_state ) ) {
+ idle_shutdown = true;
+ fprintf( stderr,
+ "Network idle for %llu seconds when SIGUSR1 received\n",
+ static_cast<unsigned long long>( time_since_remote_state / 1000 ) );
}
if ( sel.any_signal() || idle_shutdown ) {
- /* shutdown signal */
- if ( network.has_remote_addr() && (!network.shutdown_in_progress()) ) {
- network.start_shutdown();
- } else {
- break;
- }
+ /* shutdown signal */
+ if ( network.has_remote_addr() && ( !network.shutdown_in_progress() ) ) {
+ network.start_shutdown();
+ } else {
+ break;
+ }
}
-
+
/* quit if our shutdown has been acknowledged */
if ( network.shutdown_in_progress() && network.shutdown_acknowledged() ) {
- break;
+ break;
}
/* quit after shutdown acknowledgement timeout */
if ( network.shutdown_in_progress() && network.shutdown_ack_timed_out() ) {
- break;
+ break;
}
/* quit if we received and acknowledged a shutdown request */
if ( network.counterparty_shutdown_ack_sent() ) {
- break;
+ break