0

I have this function which if you connect to a system with ssh, you can call it to execute your given command on that system.

std::string sshconnection::exec_ssh_command(ssh_session session, char *command) {
    string receive = "";
    int rc, nbytes;
    char buffer[256];
    ssh_channel channel = ssh_channel_new(session);
    if( channel == NULL )
            return NULL;

    rc = ssh_channel_open_session(channel);
    if( rc != SSH_OK ) {
            ssh_channel_free(channel);
            return NULL;
    }

    rc = ssh_channel_request_exec(channel, command);
    if( rc != SSH_OK ) {
            ssh_channel_close(channel);
            ssh_channel_free(channel);
            cout << "Error";
            return NULL;
    }
    nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
    while (nbytes > 0)
    {
            if (write(1, buffer, nbytes) != (unsigned int) nbytes)
            {
                    ssh_channel_close(channel);
                    ssh_channel_free(channel);
                    return NULL;
            }
            nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
    }

    if( nbytes < 0 )
            return NULL;

    ssh_channel_send_eof(channel);
    ssh_channel_close(channel);
    ssh_channel_free(channel);

    return receive;
}

this function works great. I just don't understand that part which is about to write from buffer into a file descriptor=1 . we haven't filled receive anywhere but it is the return value. if we call this function like below:

s = exec_ssh_command(my_ssh_session, "cat /proc/stat" );

the s won't have any value, but if we do this:

std::cout<<s;

this will print s value. and of course we can't save s in a file.
can someone explain to me how is this happening?

EDIT:
function to connect to ssh:

int sshconnection::sshConnection()
{
    if( my_ssh_session == NULL ) {
            cout << "Error creating ssh session" << endl;
            return 1;
    }
    ssh_options_set(my_ssh_session, SSH_OPTIONS_HOST, "yourip");
    ssh_options_set(my_ssh_session, SSH_OPTIONS_USER, "username");
    int rc = ssh_connect(my_ssh_session);
    if( rc != SSH_OK ) {
            cout << "Error with connecting" << endl;
            ssh_free(my_ssh_session);
            return -1;
    }

    rc = ssh_userauth_password(my_ssh_session, NULL, "yourpassword");
    if( rc != SSH_AUTH_SUCCESS) {
            cout << "Error with authorization  " << ssh_get_error(my_ssh_session) << endl;
            ssh_disconnect(my_ssh_session);
            ssh_free(my_ssh_session);
            return -1;
    }
//    ssh_disconnect(my_ssh_session);
    //    ssh_free(my_ssh_session);
}
Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
fa7eme
  • 73
  • 10
  • 1
    `1` is the default `STDOUT` file descriptor. So all the code is doing is sending the data received from the ssh connection to stdout. As for why `receive` is never set that is a question for the person that wrote the code and not us. – kaylum Jul 22 '20 at 05:14
  • 2
    The variable "receive" is returned from the function but nothing is ever put into it. So the function always returns an empty string. Writing to file descriptor 1 is standard output so it should be printing what is received onto the screen even if it doesn't return it. If you want it returned and not just printed then put the result into the "receive" variable instead of doing the write. – Jerry Jeremiah Jul 22 '20 at 05:15
  • Do you need help with making it add the received characters to the "receive" variable? – Jerry Jeremiah Jul 22 '20 at 05:20
  • I followed this : https://stackoverflow.com/questions/8960087/how-to-convert-a-char-array-to-a-string and added receive = buffer after reading from buffer. @JerryJeremiah – fa7eme Jul 22 '20 at 05:31

1 Answers1

1

I know this is old, but I had the same issue. I came up with the following solution.

Use std::string::append like so receive.append(buffer, nbytes).

std::string sshconnection::exec_ssh_command(ssh_session session, char *command) {
    string receive = "";
    int rc, nbytes;
    char buffer[256];
    ssh_channel channel = ssh_channel_new(session);
    if( channel == NULL )
            return NULL;

    rc = ssh_channel_open_session(channel);
    if( rc != SSH_OK ) {
            ssh_channel_free(channel);
            return NULL;
    }

    rc = ssh_channel_request_exec(channel, command);
    if( rc != SSH_OK ) {
            ssh_channel_close(channel);
            ssh_channel_free(channel);
            cout << "Error";
            return NULL;
    }
    nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
    while (nbytes > 0)
    {
            receive.append(buffer, nbytes);
            nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
    }

    if( nbytes < 0 )
            return NULL;

    ssh_channel_send_eof(channel);
    ssh_channel_close(channel);
    ssh_channel_free(channel);

    return receive;
}
Lord of Grok
  • 323
  • 3
  • 12