Use pipe to communicate between client and server at startup

Fixes empty line on login
This commit is contained in:
Ashley Hedberg
2023-02-02 21:13:04 -05:00
committed by Alex Chernyakhovsky
parent cf542739cc
commit 4306b7cd42
+31 -7
View File
@@ -99,6 +99,7 @@
using ServerConnection = Network::Transport<Terminal::Complete, Network::UserStream>; using ServerConnection = Network::Transport<Terminal::Complete, Network::UserStream>;
static void serve( int host_fd, static void serve( int host_fd,
int pipe_fd,
Terminal::Complete &terminal, Terminal::Complete &terminal,
ServerConnection &network, ServerConnection &network,
long network_timeout, long network_timeout,
@@ -509,6 +510,12 @@ static int run_server( const char *desired_ip, const char *desired_port,
snprintf( utmp_entry, 64, "mosh [%ld]", static_cast<long int>( getpid() ) ); snprintf( utmp_entry, 64, "mosh [%ld]", static_cast<long int>( getpid() ) );
/* Fork child process */ /* Fork child process */
int pipes[2];
int success = pipe(pipes);
if (success == -1) {
perror( "pipe" );
exit( 1 );
}
pid_t child = forkpty( &master, NULL, NULL, &window_size ); pid_t child = forkpty( &master, NULL, NULL, &window_size );
if ( child == -1 ) { if ( child == -1 ) {
@@ -518,6 +525,10 @@ static int run_server( const char *desired_ip, const char *desired_port,
if ( child == 0 ) { if ( child == 0 ) {
/* child */ /* child */
if ( close( pipes[1] ) < 0 ) {
perror( "child write pipe close" );
exit( 1 );
}
/* reenable signals */ /* reenable signals */
struct sigaction sa; struct sigaction sa;
@@ -593,8 +604,12 @@ static int run_server( const char *desired_ip, const char *desired_port,
/* Wait for parent to release us. */ /* Wait for parent to release us. */
char linebuf[81]; char linebuf[81];
if (fgets(linebuf, sizeof linebuf, stdin) == NULL) { // -1, errno == EINTR -- retry
err( 1, "parent signal" ); // otherwise, give up
while ( read( pipes[0], linebuf, sizeof( linebuf ) ) == -1 ) {
if ( errno != EINTR ) {
err( 1, "parent signal" );
}
} }
Crypto::reenable_dumping_core(); Crypto::reenable_dumping_core();
@@ -604,8 +619,17 @@ static int run_server( const char *desired_ip, const char *desired_port,
sleep( 3 ); sleep( 3 );
exit( 1 ); exit( 1 );
} }
if ( close( pipes[0] ) < 0 ) {
perror( "child read pipe close" );
exit( 1 );
}
} else { } else {
/* parent */ /* parent */
if ( close(pipes[0]) < 0 ) {
perror( "parent read pipe close" );
exit( 1 );
}
/* Drop unnecessary privileges */ /* Drop unnecessary privileges */
#ifdef HAVE_PLEDGE #ifdef HAVE_PLEDGE
@@ -622,7 +646,7 @@ static int run_server( const char *desired_ip, const char *desired_port,
#endif #endif
try { try {
serve( master, terminal, *network, network_timeout, network_signaled_timeout ); serve( master, pipes[1], terminal, *network, network_timeout, network_signaled_timeout );
} catch ( const Network::NetworkException &e ) { } catch ( const Network::NetworkException &e ) {
fprintf( stderr, "Network exception: %s\n", fprintf( stderr, "Network exception: %s\n",
e.what() ); e.what() );
@@ -646,7 +670,7 @@ static int run_server( const char *desired_ip, const char *desired_port,
return 0; return 0;
} }
static void serve( int host_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 */ /* scale timeouts */
const uint64_t network_timeout_ms = static_cast<uint64_t>( network_timeout ) * 1000; const uint64_t network_timeout_ms = static_cast<uint64_t>( network_timeout ) * 1000;
@@ -822,8 +846,8 @@ static void serve( int host_fd, Terminal::Complete &terminal, ServerConnection &
/* Tell child to start login session. */ /* Tell child to start login session. */
if ( !child_released ) { if ( !child_released ) {
if ( swrite( host_fd, "\n", 1 ) < 0) { if ( close( pipe_fd ) < 0 ) {
err( 1, "child release" ); err( 1, "child release" );
} }
child_released = true; child_released = true;
} }