diff options
author | Andreas Baumann <mail@andreasbaumann.cc> | 2015-08-16 10:26:15 +0200 |
---|---|---|
committer | Andreas Baumann <mail@andreasbaumann.cc> | 2015-08-16 10:26:15 +0200 |
commit | d51319c124ce85fd965a5ff0255d1ab33e6ff4ec (patch) | |
tree | e14d45d4b00b770c056912122aadd30c9a129224 | |
parent | 556a78c5e84f6dae156fd91ee7447427a0d081d4 (diff) | |
download | cssh-d51319c124ce85fd965a5ff0255d1ab33e6ff4ec.tar.gz cssh-d51319c124ce85fd965a5ff0255d1ab33e6ff4ec.tar.bz2 |
first reliable version, ssh_channel_select is not reliable it seems
-rw-r--r-- | README | 2 | ||||
-rw-r--r-- | src/cssh.c | 161 |
2 files changed, 68 insertions, 95 deletions
@@ -37,3 +37,5 @@ References [5] http://www.gnu.org/software/parallel/ GNU parallel: very nice and powerfull, we want something simpler. +[6] https://github.com/badoo/libpssh + Libarry for multiple SSH connections using libevent and libssh2 @@ -273,6 +273,7 @@ static void cleanup_sessions( ssh_session **session, ssh_channel **channel, char } if( channel != NULL ) { if( ssh_channel_is_open( (*channel)[i] ) ) { + ssh_channel_send_eof( (*channel)[i] ); ssh_channel_close( (*channel)[i] ); ssh_channel_free( (*channel)[i] ); } @@ -470,138 +471,108 @@ int main( int argc, char *argv[] ) } } - ssh_channel *read_channel = (ssh_channel *)malloc( ( nof_sessions + 1 ) * sizeof( ssh_channel ) ); - ssh_channel *write_channel = (ssh_channel *)malloc( ( nof_sessions + 1 ) * sizeof( ssh_channel ) ); - ssh_channel *except_channel = (ssh_channel *)malloc( ( nof_sessions + 1 ) * sizeof( ssh_channel ) ); bool all_eof = false; bool *eof_sent = (bool *)malloc( ( nof_sessions + 1 ) * sizeof( bool ) ); memset( eof_sent, false, ( nof_sessions + 1 ) * sizeof( bool ) ); + bool *is_eof = (bool *)malloc( ( nof_sessions + 1 ) * sizeof( bool ) ); + memset( is_eof, false, ( nof_sessions + 1 ) * sizeof( bool ) ); while( !all_eof ) { - struct timeval timeout; - timeout.tv_sec = 1; - timeout.tv_usec = 0; all_eof = true; - memset( read_channel, 0, ( nof_sessions + 1 ) * sizeof( ssh_channel ) ); - for( unsigned int i = 0, j = 0; i < nof_sessions; i++ ) { + for( unsigned int i = 0; i < nof_sessions; i++ ) { if( !ssh_channel_is_closed( channel[i] ) && !ssh_channel_is_eof( channel[i] ) ) { - read_channel[j++] = channel[i]; all_eof = false; } } - - memset( write_channel, 0, ( nof_sessions + 1 ) * sizeof( ssh_channel ) ); - for( unsigned int i = 0, j = 0; i < nof_sessions; i++ ) { - if( !ssh_channel_is_closed( channel[i] ) && !eof_sent[i] ) { - write_channel[j++] = channel[i]; - } - } - - memset( except_channel, 0, ( nof_sessions + 1 ) * sizeof( ssh_channel ) ); - for( unsigned int i = 0, j = 0; i < nof_sessions; i++ ) { - if( !ssh_channel_is_closed( channel[i] ) ) { - except_channel[j++] = channel[i]; - } - } - - rc = ssh_channel_select( read_channel, write_channel, except_channel, &timeout ); - if( rc == SSH_ERROR ) { - fprintf( stderr, "ERROR: ssh_channel_select failed: %s\n", - ssh_get_error( session ) ); - cleanup_sessions( &session, &channel, host, port, nof_sessions, args_info.verbose_given > 0 ); - exit( EXIT_FAILURE ); - } else if( rc == SSH_EINTR ) { - continue; - } // no stdin sent to commands on remote machines for now for( unsigned int i = 0; i < nof_sessions; i++ ) { - int channel_idx = -1; - for( unsigned int j = 0; j < nof_sessions; j++ ) { - if( channel[j] == write_channel[i] ) { - channel_idx = j; - break; - } - } - if( write_channel[i] != NULL && channel_idx >= 0 && !eof_sent[channel_idx] ) { - ssh_channel_send_eof( write_channel[i] ); - eof_sent[channel_idx] = true; + if( is_eof[i] && !eof_sent[i] ) { + ssh_channel_send_eof( channel[i] ); + eof_sent[i] = true; + continue; } } for( unsigned int i = 0; i < nof_sessions; i++ ) { - if( read_channel[i] != NULL ) { - char buffer[4096]; - rc = ssh_channel_poll( read_channel[i], 0 ); - if( rc == SSH_ERROR ) { - fprintf( stderr, "ERROR: ssh_channel_poll on stdout failed: %s\n", - ssh_get_error( ssh_channel_get_session( read_channel[i] ) ) ); + char buffer[4096]; + rc = ssh_channel_poll( channel[i], 0 ); + if( rc == SSH_ERROR ) { + fprintf( stderr, "ERROR: ssh_channel_poll on stdout failed: %s\n", + ssh_get_error( ssh_channel_get_session( channel[i] ) ) ); + cleanup_sessions( &session, &channel, host, port, nof_sessions, args_info.verbose_given > 0 ); + exit( EXIT_FAILURE ); + } + + if( rc > 0 ) { + unsigned int nread = ssh_channel_read_nonblocking( channel[i], buffer, sizeof( buffer ), 0 ); + if( nread == SSH_ERROR ) { + fprintf( stderr, "ERROR: ssh_channel_read_nonblocking on stdout failed: %s\n", + ssh_get_error( channel[i] ) ); cleanup_sessions( &session, &channel, host, port, nof_sessions, args_info.verbose_given > 0 ); exit( EXIT_FAILURE ); } - - if( rc > 0 ) { - unsigned int nread = ssh_channel_read_nonblocking( read_channel[i], buffer, sizeof( buffer ), 0 ); - if( nread == SSH_ERROR ) { - fprintf( stderr, "ERROR: ssh_channel_read_nonblocking on stdout failed: %s\n", - ssh_get_error( ssh_channel_get_session( read_channel[i] ) ) ); + + if( nread == 0 ) { + is_eof[i] = true; + } + + if( nread > 0 ) { + size_t wrc = fwrite( buffer, 1, nread, stdout ); + if( wrc < 0 ) { + fprintf( stderr, "ERROR: while writing to stdout: %s\n", + strerror( errno ) ); cleanup_sessions( &session, &channel, host, port, nof_sessions, args_info.verbose_given > 0 ); exit( EXIT_FAILURE ); } - if( nread > 0 ) { - size_t wrc = fwrite( buffer, 1, nread, stdout ); - if( wrc < 0 ) { - fprintf( stderr, "ERROR: while writing to stdout: %s\n", - strerror( errno ) ); - cleanup_sessions( &session, &channel, host, port, nof_sessions, args_info.verbose_given > 0 ); - exit( EXIT_FAILURE ); - } - - if( wrc != nread ) { - fprintf( stderr, "ERROR: Write mismatch on stdout (%zu != %d)\n", - wrc, nread ); - cleanup_sessions( &session, &channel, host, port, nof_sessions, args_info.verbose_given > 0 ); - exit( EXIT_FAILURE ); - } + if( wrc != nread ) { + fprintf( stderr, "ERROR: Write mismatch on stdout (%zu != %d)\n", + wrc, nread ); + cleanup_sessions( &session, &channel, host, port, nof_sessions, args_info.verbose_given > 0 ); + exit( EXIT_FAILURE ); } } + } - rc = ssh_channel_poll( read_channel[i], 1 ); - if( rc == SSH_ERROR ) { - fprintf( stderr, "ERROR: ssh_channel_poll on stderr failed: %s\n", - ssh_get_error( ssh_channel_get_session( read_channel[i] ) ) ); + rc = ssh_channel_poll( channel[i], 1 ); + if( rc == SSH_ERROR ) { + fprintf( stderr, "ERROR: ssh_channel_poll on stderr failed: %s\n", + ssh_get_error( session[i] ) ); + cleanup_sessions( &session, &channel, host, port, nof_sessions, args_info.verbose_given > 0 ); + exit( EXIT_FAILURE ); + } + + if( rc > 0 ) { + unsigned int nread = ssh_channel_read_nonblocking( channel[i], buffer, sizeof( buffer ), 1 ); + if( nread == SSH_ERROR ) { + fprintf( stderr, "ERROR: ssh_channel_read_nonblocking on stderr failed: %s\n", + ssh_get_error( session[i] ) ); cleanup_sessions( &session, &channel, host, port, nof_sessions, args_info.verbose_given > 0 ); exit( EXIT_FAILURE ); } - - if( rc > 0 ) { - unsigned int nread = ssh_channel_read_nonblocking( read_channel[i], buffer, sizeof( buffer ), 1 ); - if( nread == SSH_ERROR ) { - fprintf( stderr, "ERROR: ssh_channel_read_nonblocking on stderr failed: %s\n", - ssh_get_error( ssh_channel_get_session( read_channel[i] ) ) ); + + if( nread > 0 ) { + size_t wrc = fwrite( buffer, 1, nread, stderr ); + if( wrc < 0 ) { + fprintf( stderr, "ERROR: while writting to stderr: %s\n", + strerror( errno ) ); cleanup_sessions( &session, &channel, host, port, nof_sessions, args_info.verbose_given > 0 ); exit( EXIT_FAILURE ); } - if( nread > 0 ) { - size_t wrc = fwrite( buffer, 1, nread, stderr ); - if( wrc < 0 ) { - fprintf( stderr, "ERROR: while writting to stderr: %s\n", - strerror( errno ) ); - cleanup_sessions( &session, &channel, host, port, nof_sessions, args_info.verbose_given > 0 ); - exit( EXIT_FAILURE ); - } - - if( wrc != nread ) { - fprintf( stderr, "ERROR: Write mismatch on stderr (%zu != %d)\n", - wrc, nread ); - cleanup_sessions( &session, &channel, host, port, nof_sessions, args_info.verbose_given > 0 ); - exit( EXIT_FAILURE ); - } + if( wrc != nread ) { + fprintf( stderr, "ERROR: Write mismatch on stderr (%zu != %d)\n", + wrc, nread ); + cleanup_sessions( &session, &channel, host, port, nof_sessions, args_info.verbose_given > 0 ); + exit( EXIT_FAILURE ); } } + + if( nread == 0 ) { + is_eof[i] = true; + } } } } |