Line data Source code
1 : /*
2 : Mosh: the mobile shell
3 : Copyright 2012 Keith Winstein
4 :
5 : This program is free software: you can redistribute it and/or modify
6 : it under the terms of the GNU General Public License as published by
7 : the Free Software Foundation, either version 3 of the License, or
8 : (at your option) any later version.
9 :
10 : This program is distributed in the hope that it will be useful,
11 : but WITHOUT ANY WARRANTY; without even the implied warranty of
12 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 : GNU General Public License for more details.
14 :
15 : You should have received a copy of the GNU General Public License
16 : along with this program. If not, see <http://www.gnu.org/licenses/>.
17 :
18 : In addition, as a special exception, the copyright holders give
19 : permission to link the code of portions of this program with the
20 : OpenSSL library under certain conditions as described in each
21 : individual source file, and distribute linked combinations including
22 : the two.
23 :
24 : You must obey the GNU General Public License in all respects for all
25 : of the code used other than OpenSSL. If you modify file(s) with this
26 : exception, you may extend this exception to your version of the
27 : file(s), but you are not obligated to do so. If you do not wish to do
28 : so, delete this exception statement from your version. If you delete
29 : this exception statement from all source files in the program, then
30 : also delete it here.
31 : */
32 :
33 : #include "config.h"
34 : #include "version.h"
35 :
36 : #include <stdlib.h>
37 : #include <unistd.h>
38 :
39 : #include "stmclient.h"
40 : #include "crypto.h"
41 : #include "locale_utils.h"
42 : #include "fatal_assert.h"
43 :
44 : /* These need to be included last because of conflicting defines. */
45 : /*
46 : * stmclient.h includes termios.h, and that will break termio/termios pull in on Solaris.
47 : * The solution is to include termio.h also.
48 : * But Mac OS X doesn't have termio.h, so this needs a guard.
49 : */
50 : #ifdef HAVE_TERMIO_H
51 : #include <termio.h>
52 : #endif
53 :
54 : #if defined HAVE_NCURSESW_CURSES_H
55 : # include <ncursesw/curses.h>
56 : # include <ncursesw/term.h>
57 : #elif defined HAVE_NCURSESW_H
58 : # include <ncursesw.h>
59 : # include <term.h>
60 : #elif defined HAVE_NCURSES_CURSES_H
61 : # include <ncurses/curses.h>
62 : # include <ncurses/term.h>
63 : #elif defined HAVE_NCURSES_H
64 : # include <ncurses.h>
65 : # include <term.h>
66 : #elif defined HAVE_CURSES_H
67 : # include <curses.h>
68 : # include <term.h>
69 : #else
70 : # error "SysV or X/Open-compatible Curses header file required"
71 : #endif
72 :
73 0 : static void print_version( FILE *file )
74 : {
75 0 : fputs( "mosh-client (" PACKAGE_STRING ") [build " BUILD_VERSION "]\n"
76 : "Copyright 2012 Keith Winstein <mosh-devel@mit.edu>\n"
77 : "License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.\n"
78 : "This is free software: you are free to change and redistribute it.\n"
79 : "There is NO WARRANTY, to the extent permitted by law.\n", file );
80 : }
81 :
82 0 : static void print_usage( FILE *file, const char *argv0 )
83 : {
84 0 : print_version( file );
85 0 : fprintf( file, "\nUsage: %s [-# 'ARGS'] IP PORT\n"
86 : " %s -c\n", argv0, argv0 );
87 0 : }
88 :
89 452 : static void print_colorcount( void )
90 : {
91 : /* check colors */
92 452 : setupterm((char *)0, 1, (int *)0);
93 :
94 452 : char colors_name[] = "colors";
95 452 : int color_val = tigetnum( colors_name );
96 452 : if ( color_val == -2 ) {
97 0 : fprintf( stderr, "Invalid terminfo numeric capability: %s\n",
98 : colors_name );
99 : }
100 :
101 452 : printf( "%d\n", color_val );
102 452 : }
103 :
104 : #ifdef NACL
105 : int mosh_main( int argc, char *argv[] )
106 : #else
107 900 : int main( int argc, char *argv[] )
108 : #endif
109 : {
110 900 : unsigned int verbose = 0;
111 : /* For security, make sure we don't dump core */
112 900 : Crypto::disable_dumping_core();
113 :
114 : /* Detect edge case */
115 900 : fatal_assert( argc > 0 );
116 :
117 : /* Get arguments */
118 2696 : for ( int i = 1; i < argc; i++ ) {
119 1796 : if ( 0 == strcmp( argv[ i ], "--help" ) ) {
120 0 : print_usage( stdout, argv[ 0 ] );
121 0 : exit( 0 );
122 : }
123 1796 : if ( 0 == strcmp( argv[ i ], "--version" ) ) {
124 0 : print_version( stdout );
125 0 : exit( 0 );
126 : }
127 : }
128 :
129 : int opt;
130 1348 : while ( (opt = getopt( argc, argv, "#:cv" )) != -1 ) {
131 900 : switch ( opt ) {
132 : case '#':
133 : // Ignore the original arguments to mosh wrapper
134 : break;
135 452 : case 'c':
136 452 : print_colorcount();
137 452 : exit( 0 );
138 0 : break;
139 0 : case 'v':
140 0 : verbose++;
141 0 : break;
142 0 : default:
143 0 : print_usage( stderr, argv[ 0 ] );
144 0 : exit( 1 );
145 1348 : break;
146 : }
147 : }
148 :
149 448 : char *ip, *desired_port;
150 :
151 448 : if ( argc - optind != 2 ) {
152 0 : print_usage( stderr, argv[ 0 ] );
153 0 : exit( 1 );
154 : }
155 :
156 448 : ip = argv[ optind ];
157 448 : desired_port = argv[ optind + 1 ];
158 :
159 : /* Sanity-check arguments */
160 448 : if ( desired_port
161 448 : && ( strspn( desired_port, "0123456789" ) != strlen( desired_port ) ) ) {
162 0 : fprintf( stderr, "%s: Bad UDP port (%s)\n\n", argv[ 0 ], desired_port );
163 0 : print_usage( stderr, argv[ 0 ] );
164 0 : exit( 1 );
165 : }
166 :
167 : /* Read key from environment */
168 448 : char *env_key = getenv( "MOSH_KEY" );
169 448 : if ( env_key == NULL ) {
170 0 : fputs( "MOSH_KEY environment variable not found.\n", stderr );
171 0 : exit( 1 );
172 : }
173 :
174 : /* Read prediction preference */
175 448 : char *predict_mode = getenv( "MOSH_PREDICTION_DISPLAY" );
176 : /* can be NULL */
177 :
178 : /* Read prediction insertion preference */
179 448 : char *predict_overwrite = getenv( "MOSH_PREDICTION_OVERWRITE" );
180 : /* can be NULL */
181 :
182 896 : string key( env_key );
183 :
184 448 : if ( unsetenv( "MOSH_KEY" ) < 0 ) {
185 0 : perror( "unsetenv" );
186 0 : exit( 1 );
187 : }
188 :
189 : /* Adopt native locale */
190 448 : set_native_locale();
191 :
192 448 : bool success = false;
193 448 : try {
194 448 : STMClient client( ip, desired_port, key.c_str(), predict_mode, verbose, predict_overwrite );
195 448 : client.init();
196 :
197 448 : try {
198 448 : success = client.main();
199 0 : } catch ( ... ) {
200 0 : client.shutdown();
201 0 : throw;
202 0 : }
203 :
204 448 : client.shutdown();
205 448 : } catch ( const Network::NetworkException &e ) {
206 0 : fprintf( stderr, "Network exception: %s\r\n",
207 0 : e.what() );
208 0 : success = false;
209 0 : } catch ( const Crypto::CryptoException &e ) {
210 0 : fprintf( stderr, "Crypto exception: %s\r\n",
211 0 : e.what() );
212 0 : success = false;
213 0 : } catch ( const std::exception &e ) {
214 0 : fprintf( stderr, "Error: %s\r\n", e.what() );
215 0 : success = false;
216 0 : }
217 :
218 448 : printf( "[mosh is exiting.]\n" );
219 :
220 448 : return !success;
221 : }
|