From feb64eec5266cd69425741af963f091c1c1b89eb Mon Sep 17 00:00:00 2001 From: Keith Winstein Date: Mon, 13 Feb 2012 05:43:07 -0500 Subject: [PATCH] Make utmp entries using utempter --- configure.ac | 1 + debian/control | 4 ++-- src/frontend/Makefile.am | 2 +- src/frontend/mosh-server.cc | 44 +++++++++++++++++++++++++++++++++- src/network/network.h | 2 ++ src/network/networktransport.h | 2 ++ 6 files changed, 51 insertions(+), 4 deletions(-) diff --git a/configure.ac b/configure.ac index 0d99e9b..2fec0ad 100644 --- a/configure.ac +++ b/configure.ac @@ -12,6 +12,7 @@ AC_PROG_CXX AC_PROG_RANLIB # Checks for libraries. +AC_SEARCH_LIBS([utempter_remove_added_record], [utempter], , AC_MSG_ERROR([Unable to find libutempter.])) # Checks for header files. AC_CHECK_HEADERS([arpa/inet.h fcntl.h langinfo.h limits.h locale.h netinet/in.h stddef.h stdint.h stdlib.h string.h sys/ioctl.h sys/socket.h sys/time.h termios.h unistd.h wchar.h wctype.h]) diff --git a/debian/control b/debian/control index 7cd7c36..c4719a5 100644 --- a/debian/control +++ b/debian/control @@ -2,7 +2,7 @@ Source: mosh Section: net Priority: optional Maintainer: Keith Winstein -Build-Depends: debhelper (>= 8.0.0), autotools-dev, protobuf-compiler, libprotobuf-dev, dh-autoreconf, pkg-config +Build-Depends: debhelper (>= 8.0.0), autotools-dev, protobuf-compiler, libprotobuf-dev, dh-autoreconf, pkg-config, libutempter-dev Standards-Version: 3.9.2 Homepage: http://mosh.mit.edu Vcs-Git: git://github.com/keithw/mosh.git @@ -10,7 +10,7 @@ Vcs-Browser: http://github.com/keithw/mosh Package: mosh Architecture: any -Depends: ${shlibs:Depends}, ${misc:Depends}, libprotobuf-lite7, libio-pty-perl, openssh-client +Depends: ${shlibs:Depends}, ${misc:Depends}, libprotobuf-lite7, libio-pty-perl, openssh-client, libutempter0 Description: Mobile shell that supports roaming and intelligent local echo Mosh is a remote terminal application that supports: - intermittent network connectivity, diff --git a/src/frontend/Makefile.am b/src/frontend/Makefile.am index e990955..ce84fec 100644 --- a/src/frontend/Makefile.am +++ b/src/frontend/Makefile.am @@ -1,7 +1,7 @@ AM_CPPFLAGS = -I$(srcdir)/../statesync -I$(srcdir)/../terminal -I$(srcdir)/../network -I$(srcdir)/../crypto -I$(builddir)/../protobufs -I$(srcdir)/../util AM_CXXFLAGS = --std=c++0x -pedantic -Werror -Wall -Wextra -Weffc++ -fno-default-inline -pipe LIBS = $(protobuf_lite_LIBS) -LDADD = ../crypto/libmoshcrypto.a ../network/libmoshnetwork.a ../statesync/libmoshstatesync.a ../terminal/libmoshterminal.a ../util/libmoshutil.a ../protobufs/libmoshprotos.a -lutil -lrt -lm +LDADD = ../crypto/libmoshcrypto.a ../network/libmoshnetwork.a ../statesync/libmoshstatesync.a ../terminal/libmoshterminal.a ../util/libmoshutil.a ../protobufs/libmoshprotos.a -lutil -lrt -lm -lutempter bin_PROGRAMS = mosh-client mosh-server diff --git a/src/frontend/mosh-server.cc b/src/frontend/mosh-server.cc index 749d64f..652c295 100644 --- a/src/frontend/mosh-server.cc +++ b/src/frontend/mosh-server.cc @@ -31,6 +31,10 @@ #include #include #include +#include +#include +#include +#include #include "completeterminal.h" #include "swrite.h" @@ -126,7 +130,7 @@ int main( int argc, char *argv[] ) } /* Fork child process */ - pid_t child = forkpty( &master, NULL, &child_termios, NULL ); + pid_t child = forkpty( &master, NULL, &child_termios, &window_size ); if ( child == -1 ) { perror( "forkpty" ); @@ -178,6 +182,11 @@ int main( int argc, char *argv[] ) exit( 0 ); } else { /* parent */ + /* make utmp entry */ + char tmp[ 64 ]; + snprintf( tmp, 64, "mosh [%d]", getpid() ); + utempter_add_record( master, tmp ); + try { serve( master, terminal, network ); } catch ( Network::NetworkException e ) { @@ -192,6 +201,8 @@ int main( int argc, char *argv[] ) perror( "close" ); exit( 1 ); } + + utempter_remove_added_record(); } printf( "\n[mosh-server is exiting.]\n" ); @@ -228,6 +239,10 @@ void serve( int host_fd, Terminal::Complete &terminal, ServerConnection &network uint64_t last_remote_num = network.get_remote_state_num(); + bool connected_utmp = false; + struct in_addr saved_addr; + saved_addr.s_addr = 0; + while ( 1 ) { try { int active_fds = poll( pollfds, 3, network.wait_time() ); @@ -271,6 +286,20 @@ void serve( int host_fd, Terminal::Complete &terminal, ServerConnection &network if ( swrite( host_fd, terminal_to_host.c_str(), terminal_to_host.length() ) < 0 ) { break; } + + /* update utmp entry if we have become "connected" */ + if ( (!connected_utmp) + || ( saved_addr.s_addr != network.get_remote_ip().s_addr ) ) { + utempter_remove_added_record(); + + saved_addr = network.get_remote_ip(); + + char tmp[ 64 ]; + snprintf( tmp, 64, "%s via mosh [%d]", inet_ntoa( saved_addr ), getpid() ); + utempter_add_record( host_fd, tmp ); + + connected_utmp = true; + } } } @@ -350,6 +379,19 @@ void serve( int host_fd, Terminal::Complete &terminal, ServerConnection &network break; } + /* update utmp if has been more than 10 seconds since heard from client */ + if ( connected_utmp ) { + if ( network.get_latest_remote_state().timestamp < Network::timestamp() - 10000 ) { + utempter_remove_added_record(); + + char tmp[ 64 ]; + snprintf( tmp, 64, "mosh [%d]", getpid() ); + utempter_add_record( host_fd, tmp ); + + connected_utmp = false; + } + } + network.tick(); } catch ( Network::NetworkException e ) { fprintf( stderr, "%s: %s\n", e.function.c_str(), strerror( e.the_errno ) ); diff --git a/src/network/network.h b/src/network/network.h index 5efd9d9..9cf3130 100644 --- a/src/network/network.h +++ b/src/network/network.h @@ -117,6 +117,8 @@ namespace Network { uint64_t timeout( void ) const; double get_SRTT( void ) const { return SRTT; } + + const struct in_addr & get_remote_ip( void ) const { return remote_addr.sin_addr; } }; } diff --git a/src/network/networktransport.h b/src/network/networktransport.h index 38ae494..05586cd 100644 --- a/src/network/networktransport.h +++ b/src/network/networktransport.h @@ -101,6 +101,8 @@ namespace Network { uint64_t get_sent_state_late_acked( void ) const { return sent_state_late_acked; } unsigned int send_interval( void ) const { return sender.send_interval(); } + + const struct in_addr & get_remote_ip( void ) const { return connection.get_remote_ip(); } }; }