From 0d636f011868e55edaffbe1d5a08a85d5dd9bd8c Mon Sep 17 00:00:00 2001 From: Ashley Hedberg Date: Thu, 2 Feb 2023 21:13:04 -0500 Subject: [PATCH] Use pipe to communicate between client and server at startup Fixes empty line on login --- src/frontend/mosh-server.cc | 38 ++++++++++++++++++++++++++++++------- 1 file changed, 31 insertions(+), 7 deletions(-) diff --git a/src/frontend/mosh-server.cc b/src/frontend/mosh-server.cc index cfbd1706c..e258d1c21 100644 --- a/src/frontend/mosh-server.cc +++ b/src/frontend/mosh-server.cc @@ -99,6 +99,7 @@ using ServerConnection = Network::Transport; static void serve( int host_fd, + int pipe_fd, Terminal::Complete &terminal, ServerConnection &network, 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( getpid() ) ); /* 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 ); if ( child == -1 ) { @@ -518,6 +525,10 @@ static int run_server( const char *desired_ip, const char *desired_port, if ( child == 0 ) { /* child */ + if ( close( pipes[1] ) < 0 ) { + perror( "child write pipe close" ); + exit( 1 ); + } /* reenable signals */ 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. */ char linebuf[81]; - if (fgets(linebuf, sizeof linebuf, stdin) == NULL) { - err( 1, "parent signal" ); + // -1, errno == EINTR -- retry + // otherwise, give up + while ( read( pipes[0], linebuf, sizeof( linebuf ) ) == -1 ) { + if ( errno != EINTR ) { + err( 1, "parent signal" ); + } } Crypto::reenable_dumping_core(); @@ -604,8 +619,17 @@ static int run_server( const char *desired_ip, const char *desired_port, sleep( 3 ); exit( 1 ); } + + if ( close( pipes[0] ) < 0 ) { + perror( "child read pipe close" ); + exit( 1 ); + } } else { - /* parent */ + /* parent */ + if ( close(pipes[0]) < 0 ) { + perror( "parent read pipe close" ); + exit( 1 ); + } /* Drop unnecessary privileges */ #ifdef HAVE_PLEDGE @@ -622,7 +646,7 @@ static int run_server( const char *desired_ip, const char *desired_port, #endif 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 ) { fprintf( stderr, "Network exception: %s\n", e.what() ); @@ -646,7 +670,7 @@ static int run_server( const char *desired_ip, const char *desired_port, 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 */ const uint64_t network_timeout_ms = static_cast( network_timeout ) * 1000; @@ -822,8 +846,8 @@ static void serve( int host_fd, Terminal::Complete &terminal, ServerConnection & /* Tell child to start login session. */ if ( !child_released ) { - if ( swrite( host_fd, "\n", 1 ) < 0) { - err( 1, "child release" ); + if ( close( pipe_fd ) < 0 ) { + err( 1, "child release" ); } child_released = true; }