summaryrefslogtreecommitdiff
path: root/src/cssh.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cssh.c')
-rw-r--r--src/cssh.c72
1 files changed, 61 insertions, 11 deletions
diff --git a/src/cssh.c b/src/cssh.c
index dddbaeb..d09f2f9 100644
--- a/src/cssh.c
+++ b/src/cssh.c
@@ -24,8 +24,14 @@
#include "options.h"
#include "version.h"
+#include "linenoise.h"
+
#define BUFSIZE 4096
#define DEFAULT_SSH_PORT 22
+#define DEFAULT_CMD_SIZE 2048
+#define DEFAULT_CLI_HISTORY_LENGTH 1024
+#define DEFAULT_PROMPT "cssh> "
+#define HISTORY_FILE ".cssh_history"
typedef enum auth_state_e {
CSSH_AUTH_INIT,
@@ -43,7 +49,8 @@ typedef enum auth_state_e {
typedef enum execution_mode_e {
CSSH_EXECUTE_UNKNOWN,
CSSH_EXECUTE_AS_SSH,
- CSSH_EXECUTE_AS_SCP
+ CSSH_EXECUTE_AS_SCP,
+ CSSH_EXECUTE_AS_CLI
} execution_mode_e;
typedef struct ssh_data_t {
@@ -440,7 +447,7 @@ static void cleanup_sessions( ssh_session **session, ssh_data_t **ssh_data, scp_
if( verbose ) {
fprintf( stderr, "Disconnecting from '%s', port %d..\n", host[i], port[i] );
}
- if( ssh_data != NULL ) {
+ if( *ssh_data != NULL ) {
ssh_channel *channel = &(*ssh_data)[i].channel;
if( ssh_channel_is_open( *channel ) ) {
ssh_channel_send_eof( *channel );
@@ -491,9 +498,11 @@ static void cleanup_sessions( ssh_session **session, ssh_data_t **ssh_data, scp_
}
if( ssh_data != NULL ) {
free( *ssh_data );
+ *ssh_data = NULL;
}
if( scp_data != NULL ) {
free( *scp_data );
+ *scp_data = NULL;
}
free( *session );
free( *host );
@@ -566,6 +575,9 @@ int main( int argc, char *argv[] )
case CSSH_EXECUTE_AS_SCP:
break;
+
+ case CSSH_EXECUTE_AS_CLI:
+ break;
}
if( parse_options_and_arguments( argc, argv, &args_info ) != 0 ) {
@@ -585,13 +597,18 @@ int main( int argc, char *argv[] )
unsigned int nof_sessions = 0;
char **host = NULL;
unsigned short *port = NULL;
- char cmd[1024];
+ char *cmd = NULL;
copy_direction_e copy_direction = CSSH_COPY_DIRECTION_DOWNLOAD;
char *local_directory = NULL;
char *remote_directory = NULL;
-
+ bool first_interactive = true;
+ char history_filename[1024];
+
switch( execution_mode ) {
case CSSH_EXECUTE_AS_SSH: {
+
+ cmd = (char *)malloc( DEFAULT_CMD_SIZE );
+
unsigned int command_pos = 0;
// command line arguments are '[user@]host'
@@ -618,16 +635,15 @@ int main( int argc, char *argv[] )
if( args_info.inputs_num > 0 ) {
for( int i = command_pos; i < args_info.inputs_num; i++ ) {
if( i != command_pos ) {
- strncat( cmd, " ", sizeof( cmd ) - strlen( cmd ) - 1 );
+ strncat( cmd, " ", DEFAULT_CMD_SIZE - strlen( cmd ) - 1 );
}
- strncat( cmd, args_info.inputs[i], sizeof( cmd ) - strlen( cmd ) - 1 );
+ strncat( cmd, args_info.inputs[i], DEFAULT_CMD_SIZE - strlen( cmd ) - 1 );
}
}
// later, this is the sign to get into CLI mode
if( cmd[0] == '\0' ) {
- fprintf( stderr, "ERROR: Empty command, no interactive CLI supported currently\n" );
- exit( EXIT_FAILURE );
+ execution_mode = CSSH_EXECUTE_AS_CLI;
}
} break;
@@ -718,6 +734,7 @@ int main( int argc, char *argv[] )
} break;
+ case CSSH_EXECUTE_AS_CLI:
case CSSH_EXECUTE_UNKNOWN:
break;
}
@@ -755,7 +772,7 @@ int main( int argc, char *argv[] )
}
int verbosity = SSH_LOG_NOLOG;
- if( args_info.verbose_given > 0 ) {
+ if( args_info.verbose_given > 1 ) {
verbosity += args_info.verbose_given;
}
@@ -934,11 +951,38 @@ int main( int argc, char *argv[] )
cssh_msleep( 10 );
}
+
+ // in CLI mode get next command from linenoise
+
+CLI_NEXT_CMD:
+ if( execution_mode == CSSH_EXECUTE_AS_CLI ) {
+ if( first_interactive ) {
+ puts( "Entering interactive shell mode.. Press Ctrl-D or Ctrl-C to terminate." );
+ first_interactive = false;
+ linenoiseSetMultiLine( 1 );
+ linenoiseHistorySetMaxLen( DEFAULT_CLI_HISTORY_LENGTH );
+
+ char *home = getenv( "HOME" );
+ if( home != NULL ) {
+ snprintf( history_filename, sizeof( history_filename ), "%s/%s", home, HISTORY_FILE );
+ linenoiseHistoryLoad( history_filename );
+ }
+ }
+ cmd = linenoise( DEFAULT_PROMPT );
+ if( cmd == NULL ) {
+ puts( "EOF received.. Terminating interactive mode." );
+ if( cmd != NULL ) linenoiseFree( cmd );
+ linenoiseHistorySave( history_filename );
+ goto SHELL_EOF;
+ }
+ linenoiseHistoryAdd( cmd );
+ }
// execution/copy phase
switch( execution_mode ) {
- case CSSH_EXECUTE_AS_SSH: {
+ case CSSH_EXECUTE_AS_SSH:
+ case CSSH_EXECUTE_AS_CLI: {
// explicit low-level handling of channels in SSH mode
@@ -1096,6 +1140,12 @@ int main( int argc, char *argv[] )
cssh_msleep( 1 );
}
+ if( execution_mode == CSSH_EXECUTE_AS_CLI ) {
+ if( cmd != NULL ) linenoiseFree( cmd );
+ goto CLI_NEXT_CMD;
+ }
+
+SHELL_EOF:
cleanup_sessions( &session, &ssh_data, NULL, host, port, nof_sessions, args_info.verbose_given > 0 );
} break;
@@ -1437,7 +1487,7 @@ int main( int argc, char *argv[] )
case CSSH_EXECUTE_UNKNOWN:
break;
}
-
+
// the end
exit( EXIT_SUCCESS );