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

Reply via email to