#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <netdb.h>
#include <sys/errno.h>
#include <fcntl.h>

#include <stdio.h>
#include <string.h>

#include "libssh2.h"

void trim(char *s, const int len)
{
    int end = len - 1;
    int start = 0;
    int i = 0;

    while ((start < len) && (s[start] <= ' '))
    {
        start++;
    }

    while ((start < end) && (s[end] <= ' '))
    {
        end--;
    }

    if (start > end)
    {
        memset(s, '\0', len);
        return;
    }

    for (i = 0; (i + start) <= end; i++)
    {
        s[i] = s[start + i];
    }
    memset((s + i), '\0', len - i);
}

int runCommand(LIBSSH2_SESSION *session, char * command, int * byteCount)
{
	LIBSSH2_CHANNEL *channel;
	char buffer[4096];
	//char *out = "";
	int bytesRead;
	int totalBytes = 0;
	
	channel = libssh2_channel_open_session(session);
	libssh2_channel_exec(channel, command);
	
	// read data
	do
	{
		bytesRead = libssh2_channel_read(channel, buffer, 4096);
		if(bytesRead < 0)
		{
			libssh2_channel_close(channel);
			return -1;
		}
		totalBytes += bytesRead;
		// I'm sucky at C, not sure how to build the string up, maybe have to realloc?
		// no matter though, byte count shows failure if it's 0, don't need to see output
		//out = strcat(out, buffer);
	}
	while (bytesRead > 0);
	*byteCount = totalBytes;
	//printf("%i bytes read\n", totalBytes);
	
	libssh2_channel_close(channel);
	//printf("Bytes read %i, output:\n%s\n============\n", (int)strlen(out), out);
	return libssh2_channel_get_exit_status(channel);
}

int main (int argc, const char * argv[]) {
	unsigned long hostaddr;
	int sock; //, i;
	struct sockaddr_in sin;
	//const char *fingerprint;
	//char *userauthlist;
	LIBSSH2_SESSION *session;

	char *host;
	char *username;
	char *password;
	char *userHost = (char *)argv[1];
	
	if(argc < 2)
	{
		printf("usage: libssh2-test user@hostname\n");
		return 0;
	}
	
	
	
	username = strsep(&userHost, "@");
	host = strsep(&userHost, "@");
	printf("connecting to %s as %s...\n", host, username);
	
	//size_t len;
	//printf("Password: ");
	//password = fgetln(stdin, &len);
	password = getpass("Password: ");
	trim(password, strlen(password));
	
	hostaddr = inet_addr(host);
	
	sock = socket(AF_INET, SOCK_STREAM, 0);
	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;
	}

	session = libssh2_session_init();
	libssh2_session_set_blocking(session, 1);
	if (libssh2_session_startup(session, sock))
	{
		fprintf(stderr, "Failure establishing SSH session\n");
		return -1;
	}
	
	if (libssh2_userauth_password(session, username, password))
	{
		printf("\tAuthentication by password failed!\n");
		goto shutdown;
	} 
	else
	{
		printf("\tAuthentication by password succeeded.\n");
	}
	
	// run a series of commands, if echo $HOME and after return 0 bytes then we failed
	char *commands[8] = {"true", "false", "echo $HOME", "ls -lL", "ls -lL", "ls -lL", "ls -lL", "ls -lL"};
	int result;
	int i;
	for(i=0; i<8; i++)
	{
		int bytesRead;
		printf("==> Running %s\n", commands[i]);
		result = runCommand(session, commands[i], &bytesRead);
		if(i > 1 && bytesRead == 0)
			printf("*** 0 BYTES READ for a command with output\n");
		printf("<== result %i\n\n", result);
	}
    
shutdown:
	libssh2_session_disconnect(session, "Normal Shutdown, Thank you for playing");
	libssh2_session_free(session);
	sleep(1);
	close(sock);
	
    return 0;
}
