I'm new to libssh and trying to connect to a remote machine to run some commands. All of the connections and commands return without error, but then the program segfaults when leaving scope. What am I doing wrong?
Code
#include <string>
#include <iostream>
using namespace std;
#define SSH_NO_CPP_EXCEPTIONS
#include <libssh/libsshpp.hpp>
int main()
{
ssh::Session session;
//Set options
session.setOption(SSH_OPTIONS_HOST, "192.168.200.101");
session.setOption( SSH_OPTIONS_USER, "user" );
//Connect to host
session.connect();
//Authenticate user
session.userauthPassword( "password" );
//Open channel
ssh::Channel channel( session );
channel.openSession();
//Do something
channel.requestExec( "ps_aux" );
//Close channel
channel.sendEof();
channel.close();
//Disconnect
session.disconnect();
return 0;
}
GDB Trace
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff3a70a2f in ssh_channel_free () from /usr/local/lib/libssh.so.4
(gdb) where
#0 0x00007ffff3a70a2f in ssh_channel_free () from /usr/local/lib/libssh.so.4
#1 0x000000000059f436 in ssh::Channel::~Channel() ()
#2 0x000000000059e603 in main ()
After beating on it awhile, we have a working solution. The first hurdle was recognizing that the remote host must be a "known host". After that, for me, it was necessary to then source the environment before running my executable.
Last, I needed to give it some time to crunch with sleep( 1 ). Enjoy.
#include <iostream>
using namespace std;
#include <libssh/libsshpp.hpp>
int main()
{
int port = 22;
//Can use SSH_LOG_PROTOCOL here for verbose output
int verbosity = SSH_LOG_NOLOG;
ssh::Session session;
try
{
session.setOption( SSH_OPTIONS_LOG_VERBOSITY, &verbosity );
session.setOption( SSH_OPTIONS_PORT, &port );
session.setOption( SSH_OPTIONS_USER, "user" );
session.setOption( SSH_OPTIONS_HOST, "192.168.52.101" );
session.connect();
if( session.isServerKnown() != SSH_SERVER_KNOWN_OK )
{
if( session.writeKnownhost() != SSH_OK )
{
cout << "writeKnownHost failed" << endl;
}
else
{
session.connect();
}
}
if( session.userauthPassword( "password" ) != SSH_AUTH_SUCCESS )
{
cout << "failed auth" << endl;
}
ssh::Channel channel( session );
channel.openSession();
//Source environment if necessary, run executable
channel.requestExec( "source /path/to/set_env.sh; /path/to/executable/..." );
channel.close();
channel.sendEof();
//Unfortunate brute force step, the exec call needed some time
sleep( 1 );
}
catch( ssh::SshException e )
{
std::cout << "Error during connection : ";
std::cout << e.getError() << std::endl;
}
return 0;
}
Related
i have a client program that connects to a server via a TCP socket, below:
int main ( )
{
std::cout << "HunterChat client starting up" << std::endl;
std::string cmd;
std::string reply;
bool cont = true;
ClientSocket client_socket ( "localhost", PORT );
try {
while(cont) {
try {
std::cout << ">> ";
// std::getline(std::cin,cmd);
gets(cmd);
if(cmd.compare("logout") == 0) {
cont = false;
break;
}
client_socket << cmd;
client_socket >> reply;
std::cout << reply << std::endl;
}
catch ( SocketException& e) {
std::cout << "Exception was caught:" << e.description() << "\n";
}
}
}
catch ( SocketException& e ) {
std::cout << "Exception was caught:" << e.description() << "\n";
}
return 0;
}
ClientSocket is a custom class that lets me set up and use the TCP connection; the stream operator is overloaded with, the following code:
int status = ::send ( m_sock, s.c_str(), s.size(), MSG_NOSIGNAL );
if ( status == -1 )
{
return false;
}
else
{
return true;
}
The TCP connection itself is working fine, so I won't clutter the post up with more of it. The problem is that one of the available commands involves sending input to a client instance while said client is still waiting for cin input. This means that the server messages only get read and written when I type something into cin. I'm trying to avoid using multithreading, so is there any way to allow cin to be interrupted without it?
Well, you could use a loop and the function kbhit() to check for user input if you really want to. However, threading seems to me such a better solution.
#include <conio.h>
#include <iostream>
using namespace std;
int main()
{
while(1)
{
if(kbhit())
{
char x = getch();
// ...
}
// check messages asynchronously here
}
}
I wrote an example application in C++(on Eclipse Luna) using sqlapi++ libraries to connect to an Oracle database I created with sqldeveloper.
The program compiles without errors, but when I run it,nothing appears on the console.
(I am using Windows 7)
Here the Database information:
Database name:"DB Casa Editrice"
Host:localhost
SID:xe
Port:1521
And the code:
#include <iostream>
#include "SQLAPI.h"
using namespace std;
int main() {
SAConnection con; // create connection object
try {
con.Connect( "DB Casa Editrice", // database name
"system", // user name
"shruikan94", // password
SA_Oracle_Client );
cout << "We are connected!\n";
con.Disconnect();
cout << "Disconnected!\n";
}
catch( SAException &x )
{
// SAConnection::Rollback()
// can also throw an exception
// (if a network error for example),
// we will be ready
try {
// on error rollback changes
con.Rollback();
}
catch( SAException & )
{
}
// print error message
cout << "ERROR\n";
}
return 0;
}
sry but my english.
it's a simple application client-server written in C++
the operating system is OpenSUSE 13.1 Linux
I do not know how to do multi client
if you could help me I would appreciate much
All this is work with only one client
i need help, thanks
This is the
Server.cpp
#include "ServerSocket.cpp"
#include "SocketException.h"
#include <string>
#include <iostream>
int main ()
{
std::cout << "running....\n";
try
{
// Create the socket
ServerSocket server ( 2020 );
while ( true )
{
ServerSocket new_sock;
server.accept ( new_sock );
try
{
while ( true )
{
std::string data;
new_sock >> data;
std::cout << "in::" << data << std::endl;
new_sock << data; // Respuesta
}
}
catch ( SocketException& ) {}
}
}
catch ( SocketException& e )
{
std::cout << "Exception was caught:" << e.description() << "\nExiting.\n";
}
return 0;
}
This is the
Client.cpp
#include "ClientSocket.cpp"
#include "SocketException.h"
#include <iostream>
#include <string>
int main ( )
{
try
{
ClientSocket client_socket ( "localhost", 2020 );
std::string reply;
try
{
std::string Envio = "";
while(Envio != "Exit")
{
getline(std::cin, Envio);
client_socket << Envio;
client_socket >> reply;
}
}
catch ( SocketException& ) {}
std::cout << "We received this response from the server:\n\"" << reply << "\"\n";;
}
catch ( SocketException& e )
{
std::cout << "Exception was caught:" << e.description() << "\n";
}
return 0;
}
Your server stops accepting connections after the very first one, and enters an infinite loop (the inner while (true)).
How to fix this depends on how your server should serve the clients. If it accepts connection, receives request, sends reply and then forgets about the client, then you do not need the inner while (true): just << and >> operations (probably you should also close the connection), and then proceed to the next accept. If you need several connections to be alive, consider making your application multi-threaded (maybe spawning a new thread for each connection if number of connections is not large).
I am running this basic shell program in another shell. I am unable to figure out why my shell doesn't keep running after "ls" executes. I dont have an exit for it but it goes back to original shell. I have to run my shell program every time if want to use it. i figured thats what the fork() is supposed to do. I only want my shell to exit using the exit command which i coded with the if else statement. Any suggestions would be much appreciated. Oh and disregard the gettoks() parser function, i couldn't figure out how to use it for input so i wrote if else statements for the string input cmSTR rather then using the gettoks() parser. Mainly because i couldn't figure how to pass the input into it
#include <iostream>
#include <unistd.h>
#include <sys/types.h>
#include <errno.h>
#include <signal.h>
#include <cstdlib>
#include <sys/wait.h>
using namespace std;
// Initializing counters for trapping
static int cc_counter = 0;
static int cz_counter = 0;
static int cq_counter = 0;
//Functions for trap signal handler
void cc_handler( int signo )
{
++cc_counter;
}
void cz_handler( int signo )
{
++cz_counter;
}
void cq_handler( int signo )
{
++cq_counter;
}
//*********************************************************
//
// Extern Declarations
//
//*********************************************************
using namespace std;
extern "C"
{
extern char **gettoks();
}
//*********************************************************
//
// Main Function
//
//*********************************************************
int main( int argc, char *argv[] )
{
// local variables
int ii;
char **toks;
int retval;
// initialize local variables
ii = 0;
toks = NULL;
retval = 0;
char buf[1000];//Initialize of size for current working directory
string cmSTR;//String to hold input
int status;//Initialization of status for fork()
pid_t pid;//Declaration of pid
// main (infinite) loop
while( true )
{
signal( SIGINT, cc_handler );// Traps Ctrl+C
signal( SIGTSTP, cz_handler);// Traps Ctrl+Z
signal( SIGQUIT, cq_handler);// Traps Ctrl+\
//prompt and show current working directory
cout <<("RS_SHELL:") << getcwd(buf,1000) << "\t";
getline(cin ,cmSTR);//read input from keyboard
// if else loop to switch based on command input
if(cmSTR == "ls")// if ls, then execute arguement
{
execl( "/bin/ls", "ls", NULL );//System call to execute ls
}
else if(cmSTR == "exit")//if exit, then execute block of code
{
cout << "Ctrl C entered: " << ++cc_counter << "times"<< endl;
cout << "Ctrl Z entered: " << ++cz_counter << "times"<< endl;
cout << "Ctrl Back Slash entered: " << ++cq_counter << "times"<< endl;
exit(1);
}
else if(cmSTR == "guish")// if guish, execute guish shell
{
execvp("guish", NULL);
}
//if input is not any of previous commands then fork()
else if(cmSTR != "ls" && cmSTR != "exit" && cmSTR != "guish" && cmSTR != "\n")
{
pid = fork();
if (pid < 0)//Loop to fork parent and child process
{
fprintf(stderr, "Fork Failed");
exit(-1);
}
else if (pid == 0)//Child process
{
execvp("guish", NULL);//system call to execute guish shell
}
else //Parent process
{
waitpid( -1, &status,0);
exit(0);
}
}
// get arguments
toks = gettoks();
if( toks[0] != NULL )
{
// simple loop to echo all arguments
for( ii=0; toks[ii] != NULL; ii++ )
{
cout << "Argument " << ii << ": " << toks[ii] << endl;
}
if( !strcmp( toks[0], "exit" ))
break;
}
}
// return to calling environment
return( retval );
}
As you suspected, execl and its related functions overlay the current process with a new process. Thus, after the execl call that starts ls, your program won't exist any more to keep running.
If you want your shell program to stay around after running ls, you'll need to fork() before the call execl( "/bin/ls", "ls", NULL );.
Also, if you want the output from ls to appear in the same console as your shell, as I think you might be intending, you will need to pipe the output from ls back to your shell and then write that output onto your shell's console. See Writing my own shell… stuck on pipes?, for instance.
I'm using what looks to be a real nice API for streaming sockets found here:
http://www.pcs.cnu.edu/~dgame/sockets/socketsC++/sockets.html.
I'm having trouble accessing the IP of the connected user because its a private member of a class "Socket" that is used within another class "ServerSocket". My program looks exactly like the demo only it it forks processes.
// libraries
#include <signal.h>
#include <string>
#include <iostream>
// headers
#include "serversocket.hpp"
#include "socketexception.hpp"
#include "config.hpp"
using namespace std;
void sessionHandler( ServerSocket );
int main ( int argc, char** argv )
{
configClass config; // this object handles command line args
config.init( argc, argv ); // initialize config with args
pid_t childpid; // this will hold the child pid
signal(SIGCHLD, SIG_IGN); // this prevents zombie processes on *nix
try
{
ServerSocket server ( config.port ); // create the socket
cout << "server alive" << "\n";
cout << "listening on port: " << config.port << "\n";
while ( true )
{
ServerSocket new_client; // create socket stream
server.accept ( new_client ); // accept a connection to the server
switch ( childpid = fork() ) // fork the child process
{
case -1://error
cerr << "error spawning child" << "\n";
break;
case 0://in the child
sessionHandler( new_client ); // handle the new client
exit(0); // session ended normally
break;
default://in the server
cout << "child process spawned: " << childpid << "\n";
break;
}
}
}
catch ( SocketException& e ) // catch problem creating server socket
{
cerr << "error: " << e.description() << "\n";
}
return 0;
}
// function declarations
void sessionHandler( ServerSocket client )
{
try
{
while ( true )
{
string data;
client >> data;
client << data;
}
}
catch ( SocketException& e )
{
cerr << "error: " << e.description() << "\n";
}
}
So my question is, can I not access the IP of the client currently connected to the socket? If it has to be modified for that functionality, what would the cleanest way to do it be?
Thanks for suggestions
I was able to add these 2 functions that allowed me to get the IP only from the scope of main like this:
server.get_ip( new_client );
but what I'd really like is to get it like this new_client.ip();
here's my 2 functions, maybe you can help me further:
std::string Socket::get_ip( Socket& new_socket )
{
char cstr[INET_ADDRSTRLEN];
std::string str;
inet_ntop(AF_INET, &(m_addr.sin_addr), cstr, INET_ADDRSTRLEN);
str = cstr;
return str;
}
std::string ServerSocket::get_ip( ServerSocket& sock )
{
return Socket::get_ip( sock );
}
The Socket class you are using has a private data member:
sockaddr_in m_addr;
This contains the info of the client connected to the socket. You can get the human-readable address with:
char str[INET_ADDRSTRLEN];
inet_ntop(AF_INET, &(m_addr.sin_addr), str, INET_ADDRSTRLEN);
As for the changes you need to make, either make m_addr public (not recommended) or add a member function that can return a string based on the above code sample.