summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Baumann <mail@andreasbaumann.cc>2015-08-16 10:26:15 +0200
committerAndreas Baumann <mail@andreasbaumann.cc>2015-08-16 10:26:15 +0200
commitd51319c124ce85fd965a5ff0255d1ab33e6ff4ec (patch)
treee14d45d4b00b770c056912122aadd30c9a129224
parent556a78c5e84f6dae156fd91ee7447427a0d081d4 (diff)
downloadcssh-d51319c124ce85fd965a5ff0255d1ab33e6ff4ec.tar.gz
cssh-d51319c124ce85fd965a5ff0255d1ab33e6ff4ec.tar.bz2
first reliable version, ssh_channel_select is not reliable it seems
-rw-r--r--README2
-rw-r--r--src/cssh.c161
2 files changed, 68 insertions, 95 deletions
diff --git a/README b/README
index daf35d6..a65889f 100644
--- a/README
+++ b/README
@@ -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
diff --git a/src/cssh.c b/src/cssh.c
index 647d194..e16087f 100644
--- a/src/cssh.c
+++ b/src/cssh.c
@@ -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;
+ }
}
}
}