diff --git a/configure.ac b/configure.ac index 3728eee..ca51c62 100644 --- a/configure.ac +++ b/configure.ac @@ -198,7 +198,7 @@ AC_TYPE_UINTPTR_T # Checks for library functions. AC_FUNC_FORK AC_FUNC_MBRTOWC -AC_CHECK_FUNCS([gettimeofday setrlimit inet_ntoa iswprint memchr memset nl_langinfo posix_memalign setenv setlocale sigaction socket strchr strdup strncasecmp strtok strerror strtol wcwidth]) +AC_CHECK_FUNCS([gettimeofday setrlimit inet_ntoa iswprint memchr memset nl_langinfo posix_memalign setenv setlocale sigaction socket strchr strdup strncasecmp strtok strerror strtol wcwidth cfmakeraw]) AC_SEARCH_LIBS([clock_gettime], [rt], [AC_DEFINE([HAVE_CLOCK_GETTIME], [1], [Define if clock_gettime is available.])]) @@ -224,6 +224,12 @@ AC_CHECK_DECL([forkpty], , [[#include #include ]]) +AC_CHECK_LIB([util], [forkpty], [ + AC_DEFINE([HAVE_FORKPTY],, [Define if you have forkpty().]) + LIBUTIL="-lutil" + AC_SUBST([LIBUTIL]) +]) + AC_MSG_CHECKING([whether pipe2(..., O_CLOEXEC) is supported]) AC_LINK_IFELSE([AC_LANG_PROGRAM([[#define _GNU_SOURCE #include diff --git a/src/examples/Makefile.am b/src/examples/Makefile.am index 0fdf593..862ec0c 100644 --- a/src/examples/Makefile.am +++ b/src/examples/Makefile.am @@ -15,16 +15,16 @@ decrypt_LDADD = ../crypto/libmoshcrypto.a $(OPENSSL_LIBS) parse_SOURCES = parse.cc parse_CPPFLAGS = -I$(srcdir)/../terminal -I$(srcdir)/../util -parse_LDADD = ../terminal/libmoshterminal.a ../util/libmoshutil.a -lutil +parse_LDADD = ../terminal/libmoshterminal.a ../util/libmoshutil.a $(LIBUTIL) termemu_SOURCES = termemu.cc termemu_CPPFLAGS = -I$(srcdir)/../terminal -I$(srcdir)/../util -I$(srcdir)/../statesync -I../protobufs -termemu_LDADD = ../terminal/libmoshterminal.a ../util/libmoshutil.a ../statesync/libmoshstatesync.a ../protobufs/libmoshprotos.a -lutil $(TINFO_LIBS) $(protobuf_LIBS) +termemu_LDADD = ../terminal/libmoshterminal.a ../util/libmoshutil.a ../statesync/libmoshstatesync.a ../protobufs/libmoshprotos.a $(LIBUTIL) $(TINFO_LIBS) $(protobuf_LIBS) ntester_SOURCES = ntester.cc ntester_CPPFLAGS = -I$(srcdir)/../util -I$(srcdir)/../statesync -I$(srcdir)/../terminal -I$(srcdir)/../network -I$(srcdir)/../crypto -I../protobufs $(protobuf_CFLAGS) -ntester_LDADD = ../statesync/libmoshstatesync.a ../terminal/libmoshterminal.a ../network/libmoshnetwork.a ../crypto/libmoshcrypto.a ../protobufs/libmoshprotos.a ../util/libmoshutil.a -lutil -lm $(protobuf_LIBS) $(OPENSSL_LIBS) +ntester_LDADD = ../statesync/libmoshstatesync.a ../terminal/libmoshterminal.a ../network/libmoshnetwork.a ../crypto/libmoshcrypto.a ../protobufs/libmoshprotos.a ../util/libmoshutil.a $(LIBUTIL) -lm $(protobuf_LIBS) $(OPENSSL_LIBS) benchmark_SOURCES = benchmark.cc benchmark_CPPFLAGS = -I$(srcdir)/../util -I$(srcdir)/../statesync -I$(srcdir)/../terminal -I../protobufs -I$(srcdir)/../frontend -I$(srcdir)/../crypto -I$(srcdir)/../network $(protobuf_CFLAGS) -benchmark_LDADD = ../frontend/terminaloverlay.o ../statesync/libmoshstatesync.a ../terminal/libmoshterminal.a ../protobufs/libmoshprotos.a ../network/libmoshnetwork.a ../crypto/libmoshcrypto.a ../util/libmoshutil.a $(STDDJB_LDFLAGS) -lutil -lm $(TINFO_LIBS) $(protobuf_LIBS) $(OPENSSL_LIBS) +benchmark_LDADD = ../frontend/terminaloverlay.o ../statesync/libmoshstatesync.a ../terminal/libmoshterminal.a ../protobufs/libmoshprotos.a ../network/libmoshnetwork.a ../crypto/libmoshcrypto.a ../util/libmoshutil.a $(STDDJB_LDFLAGS) $(LIBUTIL) -lm $(TINFO_LIBS) $(protobuf_LIBS) $(OPENSSL_LIBS) diff --git a/src/examples/ntester.cc b/src/examples/ntester.cc index be7746f..0b8f673 100644 --- a/src/examples/ntester.cc +++ b/src/examples/ntester.cc @@ -35,6 +35,7 @@ #include "user.h" #include "fatal_assert.h" +#include "pty_compat.h" #include "networktransport.cc" #include "select.h" diff --git a/src/examples/parse.cc b/src/examples/parse.cc index 590a1c3..f259f5f 100644 --- a/src/examples/parse.cc +++ b/src/examples/parse.cc @@ -56,6 +56,7 @@ #include "swrite.h" #include "locale_utils.h" #include "fatal_assert.h" +#include "pty_compat.h" #include "select.h" const size_t buf_size = 1024; diff --git a/src/examples/termemu.cc b/src/examples/termemu.cc index b6551b3..ff2ec78 100644 --- a/src/examples/termemu.cc +++ b/src/examples/termemu.cc @@ -62,6 +62,7 @@ #include "completeterminal.h" #include "swrite.h" #include "fatal_assert.h" +#include "pty_compat.h" #include "locale_utils.h" #include "select.h" diff --git a/src/frontend/Makefile.am b/src/frontend/Makefile.am index 07cb928..a0345ae 100644 --- a/src/frontend/Makefile.am +++ b/src/frontend/Makefile.am @@ -3,7 +3,7 @@ AM_CXXFLAGS = $(WARNING_CXXFLAGS) $(PICKY_CXXFLAGS) $(HARDEN_CFLAGS) $(MISC_CXXF AM_LDFLAGS = $(HARDEN_LDFLAGS) LDADD = ../crypto/libmoshcrypto.a ../network/libmoshnetwork.a ../statesync/libmoshstatesync.a ../terminal/libmoshterminal.a ../util/libmoshutil.a ../protobufs/libmoshprotos.a -lm $(TINFO_LIBS) $(protobuf_LIBS) $(OPENSSL_LIBS) -mosh_server_LDADD = $(LDADD) -lutil +mosh_server_LDADD = $(LDADD) $(LIBUTIL) bin_PROGRAMS = diff --git a/src/frontend/mosh-server.cc b/src/frontend/mosh-server.cc index 1b42aa0..5afff25 100644 --- a/src/frontend/mosh-server.cc +++ b/src/frontend/mosh-server.cc @@ -58,14 +58,6 @@ #include #endif -#include "completeterminal.h" -#include "swrite.h" -#include "user.h" -#include "fatal_assert.h" -#include "locale_utils.h" -#include "select.h" -#include "timestamp.h" - #if HAVE_PTY_H #include #elif HAVE_UTIL_H @@ -76,6 +68,15 @@ #include #endif +#include "completeterminal.h" +#include "swrite.h" +#include "user.h" +#include "fatal_assert.h" +#include "locale_utils.h" +#include "pty_compat.h" +#include "select.h" +#include "timestamp.h" + #ifndef _PATH_BSHELL #define _PATH_BSHELL "/bin/sh" #endif diff --git a/src/frontend/stmclient.cc b/src/frontend/stmclient.cc index 00aef86..2b69f7b 100644 --- a/src/frontend/stmclient.cc +++ b/src/frontend/stmclient.cc @@ -56,6 +56,7 @@ #include "user.h" #include "fatal_assert.h" #include "locale_utils.h" +#include "pty_compat.h" #include "select.h" #include "timestamp.h" diff --git a/src/util/Makefile.am b/src/util/Makefile.am index 1b5ad54..25dc3dd 100644 --- a/src/util/Makefile.am +++ b/src/util/Makefile.am @@ -2,4 +2,4 @@ AM_CXXFLAGS = $(WARNING_CXXFLAGS) $(PICKY_CXXFLAGS) $(HARDEN_CFLAGS) $(MISC_CXXF noinst_LIBRARIES = libmoshutil.a -libmoshutil_a_SOURCES = locale_utils.cc locale_utils.h swrite.cc swrite.h dos_assert.h fatal_assert.h select.h select.cc timestamp.h timestamp.cc +libmoshutil_a_SOURCES = locale_utils.cc locale_utils.h swrite.cc swrite.h dos_assert.h fatal_assert.h select.h select.cc timestamp.h timestamp.cc pty_compat.cc pty_compat.h diff --git a/src/util/pty_compat.cc b/src/util/pty_compat.cc new file mode 100644 index 0000000..b5d800d --- /dev/null +++ b/src/util/pty_compat.cc @@ -0,0 +1,165 @@ +/* + Mosh: the mobile shell + Copyright 2012 Keith Winstein + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + In addition, as a special exception, the copyright holders give + permission to link the code of portions of this program with the + OpenSSL library under certain conditions as described in each + individual source file, and distribute linked combinations including + the two. + + You must obey the GNU General Public License in all respects for all + of the code used other than OpenSSL. If you modify file(s) with this + exception, you may extend this exception to your version of the + file(s), but you are not obligated to do so. If you do not wish to do + so, delete this exception statement from your version. If you delete + this exception statement from all source files in the program, then + also delete it here. +*/ + +#include "config.h" + +#if !defined(HAVE_FORKPTY) || !defined(HAVE_CFMAKERAW) +#include +#include +#include +#include +#include +#include +#include +#include + +#include "pty_compat.h" + +#ifndef HAVE_FORKPTY +pid_t my_forkpty( int *amaster, char *name, + const struct termios *termp, + const struct winsize *winp ) +{ + /* For Solaris */ + int master, slave; + char *slave_name; + pid_t pid; + + master = open( "/dev/ptmx", O_RDWR | O_NOCTTY ); + if ( master < 0 ) { + perror( "open(/dev/ptmx)" ); + return -1; + } + + if ( grantpt( master ) < 0 ) { + perror( "grantpt" ); + close( master ); + return -1; + } + + if ( unlockpt(master) < 0 ) { + perror( "unlockpt" ); + close( master ); + return -1; + } + + slave_name = ptsname( master ); + if ( slave_name == NULL ) { + perror( "ptsname" ); + close( master ); + return -1; + } + + slave = open( slave_name, O_RDWR | O_NOCTTY ); + if ( slave < 0 ) { + perror( "open(slave)" ); + close( master ); + return -1; + } + + if ( ioctl(slave, I_PUSH, "ptem") < 0 || + ioctl(slave, I_PUSH, "ldterm") < 0 ) { + perror( "ioctl(I_PUSH)" ); + close( slave ); + close( master ); + return -1; + } + + if ( amaster != NULL ) + *amaster = master; + + if ( name != NULL) + strcpy( name, slave_name ); + + if ( termp != NULL ) { + if ( tcsetattr( slave, TCSAFLUSH, termp ) < 0 ) { + perror( "tcsetattr" ); + exit( 1 ); + } + } + + // we need to set initial window size, or TIOCGWINSZ fails + struct winsize w; + w.ws_row = 25; + w.ws_col = 80; + w.ws_xpixel = 0; + w.ws_ypixel = 0; + if ( ioctl( slave, TIOCSWINSZ, &w) < 0 ) { + perror( "ioctl TIOCSWINSZ" ); + exit( 1 ); + } + if ( winp != NULL ) { + if ( ioctl( slave, TIOCGWINSZ, winp ) < 0 ) { + perror( "ioctl TIOCGWINSZ" ); + exit( 1 ); + } + } + + pid = fork(); + switch ( pid ) { + case -1: /* Error */ + perror( "fork()" ); + return -1; + case 0: /* Child */ + if ( setsid() < 0 ) + perror( "setsid" ); + if ( ioctl( slave, TIOCSCTTY, NULL ) < 0 ) { + perror( "ioctl" ); + return -1; + } + close( master ); + dup2( slave, STDIN_FILENO ); + dup2( slave, STDOUT_FILENO ); + dup2( slave, STDERR_FILENO ); + return 0; + default: /* Parent */ + close( slave ); + return pid; + } +} +#endif + +#ifndef HAVE_CFMAKERAW +void my_cfmakeraw( struct termios *termios_p ) +{ + termios_p->c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP + | INLCR | IGNCR | ICRNL | IXON); + termios_p->c_oflag &= ~OPOST; + termios_p->c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN); + termios_p->c_cflag &= ~(CSIZE | PARENB); + termios_p->c_cflag |= CS8; + + termios_p->c_cc[VMIN] = 1; // read() is satisfied after 1 char + termios_p->c_cc[VTIME] = 0; // No timer +} +#endif +#endif diff --git a/src/util/pty_compat.h b/src/util/pty_compat.h new file mode 100644 index 0000000..a1dc79a --- /dev/null +++ b/src/util/pty_compat.h @@ -0,0 +1,51 @@ +/* + Mosh: the mobile shell + Copyright 2012 Keith Winstein + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + In addition, as a special exception, the copyright holders give + permission to link the code of portions of this program with the + OpenSSL library under certain conditions as described in each + individual source file, and distribute linked combinations including + the two. + + You must obey the GNU General Public License in all respects for all + of the code used other than OpenSSL. If you modify file(s) with this + exception, you may extend this exception to your version of the + file(s), but you are not obligated to do so. If you do not wish to do + so, delete this exception statement from your version. If you delete + this exception statement from all source files in the program, then + also delete it here. +*/ + +#ifndef PTY_COMPAT_HPP +#define PTY_COMPAT_HPP + +#include "config.h" + +#ifndef HAVE_FORKPTY +# define forkpty my_forkpty +#endif +#ifndef HAVE_CFMAKERAW +# define cfmakeraw my_cfmakeraw +#endif + +pid_t my_forkpty( int *amaster, char *name, + const struct termios *termp, + const struct winsize *winp ); + +void my_cfmakeraw( struct termios *termios_p ); + +#endif