On Sun, Aug 05, 2007 at 04:06:55PM +0200, Thomas Harding wrote:
> So, then running this example:
> ./ssh2 127.0.0.1 tom '*****' 'cat xulu' 1 100
>
>
> >foo
> ^IP ^user ^pass ^command ^display errors if 1 ^if
> given, poll timeout in ms. If not, running in blocking mode
>
>
> * ./ssh2 127.0.0.1 tom '*****' 'cat xulu' 1 100 >foo
> > display error message. OK
> * ./ssh2 127.0.0.1 tom '*****' 'cat mbox' 1 100 >foo
> > records mbox in foo. OK
> * ./ssh2 127.0.0.1 tom '*****' 'cat xulu; cat mbox; cat mbox' 1 100 >foo
> > display error messages
> > records _partly_ mbox in foo. BAD
> * ./ssh2 127.0.0.1 tom '*****' 'cat xulu; cat mbox; cat xulu' 1 >foo
> or * ./ssh2 127.0.0.1 tom '*****' 'cat mbox' 1 >foo
> > stops while reading stderr. BAD
> * ./ssh2 127.0.0.1 tom '*****' 'cat xulu' 1 >foo
> > display error and quit. OK
> * ./ssh2 127.0.0.1 tom '*****' 'cat mbox' >foo
> > records mbox in foo. OK
* ./ssh2 127.0.0.1 tom '*****' 'cat xulu; cat mbox; cat xulu' >foo
> never reach EOF
> So, have someone a good method to read both completely stdout and
> stderr?
Joined new code with libssh2 coding style. You can uncomment line #130
to enable trace.
--
Thomas Harding
/*
* $Id: ssh2.c,v 1.3 2007/04/26 23:59:15 gknauf Exp $
*
* Sample showing how to do SSH2 exec.
*
* The sample code has default values for host name, user name, password
* and command, but you can specify them on the command line like:
*
* "ssh2 host user password command"
* "ssh2 ipaddr username password command [1 to display errors [timeout in ms]]"
*/
#include <libssh2.h>
#include <libssh2_sftp.h>
#include "config.h"
#include <string.h>
#ifdef HAVE_WINSOCK2_H
# include <winsock2.h>
#endif
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
# include <sys/socket.h>
#endif
# ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <sys/types.h>
#include <fcntl.h>
#include <errno.h>
#include <stdio.h>
#include <ctype.h>
int
main (int argc, char *argv[])
{
unsigned long hostaddr;
int sock, i, auth_pw = 1;
struct sockaddr_in sin;
const char *fingerprint;
LIBSSH2_SESSION *session;
LIBSSH2_CHANNEL *channel;
char *username = (char *) "username";
char *password = (char *) "password";
char *command = (char *) "cat mbox";
size_t bufsiz = 8193;
size_t ret = 0;
char *buf;
char *strout;
int retcount = 0;
int strlencount = 0;
int num;
int display_errors;
int set_non_blocking;
int nfds = 1;
LIBSSH2_POLLFD *fds;
LIBSSH2_POLLFD *fdserr;
int timeout = 100;
int test_err;
#ifdef WIN32
WSADATA wsadata;
WSAStartup (WINSOCK_VERSION, &wsadata);
#endif
if (argc > 1) {
hostaddr = inet_addr (argv[1]);
} else {
hostaddr = htonl (0x7F000001);
}
if (argc > 2) {
username = argv[2];
}
if (argc > 3) {
password = argv[3];
}
if (argc > 4) {
command = argv[4];
}
if (argc > 5) {
display_errors = (strtol (argv[5], NULL, 10) == 1) ? 1 : 0;
fprintf (stderr, "Display errors: %d\n", display_errors);
} else {
display_errors = 0;
}
if (argc > 6) {
set_non_blocking = 1;
timeout = strtol (argv[6], NULL, 10);
fprintf (stderr, "Timeout %d\n", timeout);
} else {
set_non_blocking = 0;
}
/* 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);
#ifndef WIN32
fcntl (sock, F_SETFL, 0);
#endif
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;
}
/* Create a session instance and start it up
* This will trade welcome banners, exchange keys, and setup crypto,
* compression, and MAC layers
*/
session = libssh2_session_init ();
if (libssh2_session_startup (session, sock)) {
fprintf (stderr, "Failure establishing SSH session\n");
return -1;
}
/* libssh2_trace (session, 7); */
/* At this point we havn't 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 (auth_pw) {
/* We could authenticate via password */
if (libssh2_userauth_password (session, username, password)) {
printf ("Authentication by password failed.\n");
goto shutdown;
}
} else {
/* Or by public key */
if (libssh2_userauth_publickey_fromfile
(session, username, "/home/username/.ssh/id_rsa.pub",
"/home/username/.ssh/id_rsa", password)) {
printf ("\tAuthentication by public key failed\n");
goto shutdown;
}
}
/* Request a shell */
if (!(channel = libssh2_channel_open_session (session))) {
fprintf (stderr, "Unable to open a session\n");
goto shutdown;
}
/* At this point the shell can be interacted with using
* libssh2_channel_read()
* libssh2_channel_read_stderr()
* libssh2_channel_write()
* libssh2_channel_write_stderr()
*
* Blocking mode may be (en|dis)abled with: libssh2_channel_set_blocking()
* If the server send EOF, libssh2_channel_eof() will return non-0
* To send EOF to the server use: libssh2_channel_send_eof()
* A channel can be closed with: libssh2_channel_close()
* A channel can be freed with: libssh2_channel_free()
*/
/* execute the command(s) */
if (libssh2_channel_exec (channel, command)) {
fprintf (stderr, "Unable to exec command\n");
goto skip_shell;
}
/* set the channel to blocking/non blocking mode */
if (set_non_blocking == 0) {
libssh2_channel_set_blocking (channel, 1);
} else {
libssh2_channel_set_blocking (channel, 0);
}
/* receive std & err outputs, display them to stdout and stderr */
while (1) {
fprintf (stderr, "\nMALLOC\n");
if ((buf = malloc (bufsiz)) == NULL)
break;
fprintf (stderr, "MALLOC OK\n");
test_err = 1;
if (set_non_blocking == 1) {
/* poll for stdout */
if ((fds = malloc (sizeof (LIBSSH2_POLLFD) * 2)) == NULL) {
fprintf (stderr, "Error while allocating poll struct\n");
goto skip_shell;
}
fds[0].type = LIBSSH2_POLLFD_CHANNEL;
fds[0].fd.channel = channel;
fds[0].events = LIBSSH2_POLLFD_POLLIN;
fds[0].revents = LIBSSH2_POLLFD_POLLIN;
fprintf (stderr, "POLLING\n");
test_err = libssh2_poll (fds, nfds, timeout);
fprintf (stderr, "POLL %d\n", test_err);
fprintf (stderr, "POLL REVENTS %ld\n", fds[0].revents);
free (fds);
}
ret = 0;
if (test_err > 0) {
/* gets stdout */
ret = libssh2_channel_read (channel, buf, bufsiz - 10);
fprintf (stderr, "STD BUFFER SIZE= %d\n", ret);
}
if (ret > 0) {
/* display stdout */
strlencount += strlen (buf);
retcount += ret;
fprintf (stderr, "RET=%d\nLEN=%d\n", ret, strlen (buf));
if ((strout = malloc (ret + 1)) != NULL) {
num = snprintf (strout, ret + 1, "%s", buf);
fprintf (stderr, "N=%d\n", num);
/* printf(strout); */
fprintf (stdout, "%s", strout);
free (strout);
}
} else {
fprintf (stderr, "\nRET=%d\n", ret);
}
free (buf);
if (display_errors == 1) {
fprintf (stderr, "BEGIN LOOPERR\n");
if (set_non_blocking == 1) {
/* poll for stderr */
if ((fdserr = malloc (sizeof (LIBSSH2_POLLFD) * 2)) == NULL) {
fprintf (stderr, "Error while allocating poll struct\n");
goto skip_shell;
}
fdserr[0].type = LIBSSH2_POLLFD_CHANNEL;
fdserr[0].fd.channel = channel;
fdserr[0].events = LIBSSH2_POLLFD_POLLEXT;
fdserr[0].revents = LIBSSH2_POLLFD_POLLEXT;
/*
fdserr[1].type = LIBSSH2_POLLFD_CHANNEL;
fdserr[1].fd.channel = channel;
fdserr[1].events = ;
fdserr[1].revents = ;
*/
fprintf (stderr, "POLLING ERRORS\n");
/* usleep (timeout); */
test_err = libssh2_poll (fdserr, nfds, timeout);
fprintf (stderr, "END POLLING ERRORS\n");
fprintf (stderr, "POLLERR %d\n", test_err);
fprintf (stderr, "POLLERR REVENTS %ld\n", fdserr[0].revents);
free (fdserr);
} else {
test_err = 1;
}
if (test_err > 0) {
/* gets and display stderr */
fprintf (stderr, "ERROR: ");
if ((buf = malloc (bufsiz)) == NULL)
break;
ret = libssh2_channel_read_stderr (channel, buf, bufsiz - 10);
fprintf (stderr, "STDERR BUFFER SIZE= %d\n", ret);
if (ret > 0) {
if ((strout = malloc (ret + 1)) != NULL) {
num = snprintf (strout, ret + 1, "%s", buf);
/* printf(strout); */
fprintf (stderr, "%s", strout);
fprintf (stderr, "NERR=%d\n", num);
} else {
fprintf (stderr, "NULL ASSIGNMENT");
}
free (strout);
} else {
fprintf (stderr, "\nSTDERR_RET=%d\n", ret);
}
free (buf);
}
}
fprintf (stderr, "BEF EOF\n");
if (libssh2_channel_eof (channel) == 1) {
/* end read at remote EOF */
fprintf (stderr, "EOF\n");
fprintf (stderr, "\nEOF: RET %d octets, STRLEN %d octets\n",
retcount, strlencount);
break;
}
fprintf (stderr, "AFT EOF\n");
}
skip_shell:
if (channel) {
libssh2_channel_free (channel);
channel = NULL;
}
/* Other channel types are supported via:
* libssh2_scp_send()
* libssh2_scp_recv()
* libssh2_channel_direct_tcpip()
*/
shutdown:
libssh2_session_disconnect (session,
"Normal Shutdown, Thank you for playing");
libssh2_session_free (session);
#ifdef WIN32
Sleep (1000);
closesocket (sock);
#else
sleep (1);
close (sock);
#endif
fprintf (stderr, "all done\n");
return 0;
}
-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems? Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/
_______________________________________________
libssh2-devel mailing list
libssh2-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/libssh2-devel