diff --git a/example/simple/Makefile.am b/example/simple/Makefile.am index 4dc63988..cfa16d92 100644 --- a/example/simple/Makefile.am +++ b/example/simple/Makefile.am @@ -8,7 +8,7 @@ noinst_PROGRAMS = ssh2 \ sftp_write sftp_write_nonblock \ sftp_mkdir sftp_mkdir_nonblock \ sftp_RW_nonblock \ - sftpdir sftpdir_nonblock + sftpdir sftpdir_nonblock ssh2_exec # the examples need the $(top_builddir)/src since when building outside of the # source dir they still need to reach the libssh2_config.h header diff --git a/example/simple/ssh2_exec.c b/example/simple/ssh2_exec.c new file mode 100644 index 00000000..4c17bc82 --- /dev/null +++ b/example/simple/ssh2_exec.c @@ -0,0 +1,251 @@ +/* + * $Id: ssh2_exec.c,v 1.1 2009/05/05 12:27:02 bagder Exp $ + * + * Sample showing how to use libssh2 to execute a command remotely. + * + * The sample code has fixed values for host name, user name, password + * and command to run. Change them to something suitable. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + + +static int waitsocket(int socket_fd, LIBSSH2_SESSION *session) +{ + struct timeval timeout; + int rc; + fd_set fd; + fd_set *writefd = NULL; + fd_set *readfd = NULL; + int dir; + + timeout.tv_sec = 10; + timeout.tv_usec = 0; + + FD_ZERO(&fd); + + FD_SET(socket_fd, &fd); + + /* now make sure we wait in the correct direction */ + dir = libssh2_session_block_directions(session); + + if(dir & LIBSSH2_SESSION_BLOCK_INBOUND) + readfd = &fd; + + if(dir & LIBSSH2_SESSION_BLOCK_OUTBOUND) + writefd = &fd; + + rc = select(socket_fd + 1, readfd, writefd, NULL, &timeout); + + return rc; +} + +int main(int argc, char *argv[]) +{ + const char *remotehost = "127.0.0.1"; + const char *commandline = "uptime"; + const char *username = "user"; + const char *password = "password"; + unsigned long hostaddr; + int sock, i; + struct sockaddr_in sin; + const char *fingerprint; + LIBSSH2_SESSION *session; + LIBSSH2_CHANNEL *channel; + int rc; + int exitcode; + int bytecount = 0; + +#ifdef WIN32 + WSADATA wsadata; + WSAStartup(MAKEWORD(2,0), &wsadata); +#endif + (void)argv; + (void)argc; + + hostaddr = inet_addr( remotehost ); + + /* Ultra basic "connect to port 22 on localhost" + * Your code is responsible for creating the socket establishing the + * connection + */ + sock = socket(AF_INET, SOCK_STREAM, 0); + + sin.sin_family = AF_INET; + sin.sin_port = htons(22); + sin.sin_addr.s_addr = hostaddr; + if (connect(sock, (struct sockaddr*)(&sin), + sizeof(struct sockaddr_in)) != 0) { + fprintf(stderr, "failed to connect!\n"); + return -1; + } + + /* We set the socket non-blocking. We do it after the connect just to + simplify the example code. */ +#ifdef F_SETFL + /* FIXME: this can/should be done in a more portable manner */ + rc = fcntl(sock, F_GETFL, 0); + fcntl(sock, F_SETFL, rc | O_NONBLOCK); +#elif defined(HAVE_IOCTLSOCKET) + ioctlsocket(sock, FIONBIO, &flag); +#else +#ifdef WIN32 + u_long mode = 1; + ioctlsocket (sock, FIONBIO, &mode); +#else +#error "add support for setting the socket non-blocking here" +#endif +#endif + + /* Create a session instance */ + session = libssh2_session_init(); + if (!session) + return -1; + + /* Since we have set non-blocking, tell libssh2 we are non-blocking */ + libssh2_session_set_blocking(session, 0); + + /* ... start it up. This will trade welcome banners, exchange keys, + * and setup crypto, compression, and MAC layers + */ + while ((rc = libssh2_session_startup(session, sock)) == + LIBSSH2_ERROR_EAGAIN); + if (rc) { + fprintf(stderr, "Failure establishing SSH session: %d\n", rc); + return -1; + } + + /* At this point we havn't yet authenticated. The first thing to do + * is check the hostkey's fingerprint against our known hosts Your app + * may have it hard coded, may go to a file, may present it to the + * user, that's your call + */ + fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_MD5); + fprintf(stderr, "Fingerprint: "); + for(i = 0; i < 16; i++) { + fprintf(stderr, "%02X ", (unsigned char)fingerprint[i]); + } + fprintf(stderr, "\n"); + + if ( strlen(password) != 0 ) { + /* We could authenticate via password */ + while ((rc = libssh2_userauth_password(session, username, password)) == + LIBSSH2_ERROR_EAGAIN); + if (rc) { + fprintf(stderr, "Authentication by password failed.\n"); + goto shutdown; + } + } + else { + /* Or by public key */ + while ((rc = libssh2_userauth_publickey_fromfile(session, username, + "/home/user/" + ".ssh/id_rsa.pub", + "/home/user/" + ".ssh/id_rsa", + password)) == + LIBSSH2_ERROR_EAGAIN); + if (rc) { + fprintf(stderr, "\tAuthentication by public key failed\n"); + goto shutdown; + } + } + +#if 0 + libssh2_trace(session, ~0 ); +#endif + + /* Exec non-blocking on the remove host */ + while( (channel = libssh2_channel_open_session(session)) == NULL && + libssh2_session_last_error(session,NULL,NULL,0) == + LIBSSH2_ERROR_EAGAIN ) + { + waitsocket(sock, session); + } + if( channel == NULL ) + { + fprintf(stderr,"Error\n"); + exit( 1 ); + } + while( (rc = libssh2_channel_exec(channel, commandline)) == + LIBSSH2_ERROR_EAGAIN ) + { + waitsocket(sock, session); + } + if( rc != 0 ) + { + fprintf(stderr,"Error\n"); + exit( 1 ); + } + for( ;; ) + { + /* loop until we block */ + int rc; + do + { + char buffer[0x4000]; + rc = libssh2_channel_read( channel, buffer, sizeof(buffer) ); + if( rc > 0 ) + { + int i; + bytecount += rc; + fprintf(stderr, "We read:\n"); + for( i=0; i < rc; ++i ) + fputc( buffer[i], stderr); + fprintf(stderr, "\n"); + } + else { + fprintf(stderr, "libssh2_channel_read returned %d\n", rc); + } + } + while( rc > 0 ); + + /* this is due to blocking that would occur otherwise so we loop on + this condition */ + if( rc == LIBSSH2_ERROR_EAGAIN ) + { + waitsocket(sock, session); + } + else + break; + } + exitcode = 127; + while( (rc = libssh2_channel_close(channel)) == LIBSSH2_ERROR_EAGAIN ) + ; + if( rc == 0 ) + { + exitcode = libssh2_channel_get_exit_status( channel ); + } + printf("\nEXIT: %d bytecount: %d\n", exitcode, bytecount); + + libssh2_channel_free(channel); + channel = NULL; + +shutdown: + + libssh2_session_disconnect(session, + "Normal Shutdown, Thank you for playing"); + libssh2_session_free(session); + +#ifdef WIN32 + closesocket(sock); +#else + close(sock); +#endif + fprintf(stderr, "all done\n"); + return 0; +} +