On Wed, Aug 01, 2007 at 05:56:53PM +0200, Thomas Harding wrote:
> 
> >>On Tue, 31 Jul 2007, Thomas Harding wrote:
> >Daniel Stenberg <[EMAIL PROTECTED]>
> >
> >>My problem is that while using libssh2_channel_read_stderr, it seems to 
> >>wait infinitely for data when no data is available, whatever channel is or 
> >>is not in blocking mode.
> >
> >Can you please provide a complete small source snippet that reproduces the 
> >problem?
> 
> Well, maybe the better will be to me to write such this, but it is not
> done... hope following code will be enough explicit.

Here is the code snippet in attachment.

This can be compiled in lieue of example/simple/ssh2.c

Note I'm a "C" newbie, and have not network programming experience.

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       


So, have someone a good method to read both completely stdout and
stderr?

-- 
Thomas Harding
/*
 * $Id: ssh2.c,v 1.3 2007/04/26 23:59:15 gknauf Exp $
 *
 * Sample showing how to do SSH2 connect.
 *
 * The sample code has default values for host name, user name, password
 * and path to copy, but you can specify them on the command line like:
 *
 * "ssh2 host user password"
 */

#include <libssh2.h>
#include <libssh2_sftp.h>
#include <libssh2_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;
  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];
    }
  else
    {
      fprintf (stderr,
	       "Usage: %s username password command [1 to display errors [timeout in ms]]",
	       argv[0]);
      return 1;

    }
  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;
    }

  /* 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 %d\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 %d\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", num);
      if (libssh2_channel_eof (channel) == 1)
	{
	  /* end read at remote EOF */
	  fprintf (stderr, "EOF\n", num);
	  fprintf (stderr, "\nEOF: RET %d octets, STRLEN %d octets\n",
		   retcount, strlencount);
	  break;
	}
      fprintf (stderr, "AFT EOF\n", num);
    }

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