diff options
Diffstat (limited to 'src/cssh.c')
-rw-r--r-- | src/cssh.c | 72 |
1 files changed, 61 insertions, 11 deletions
@@ -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 ); |