/***********************************************************
 * loadclient                                              *
 * deliver local load to server                            *
 * Verteilte Systeme II Kapitel 10                         *
 ***********************************************************
 * 1999 by Frank Kargl (frank.kargl@informatik.uni-ulm.de) *
 ***********************************************************
 * Usage: loadserver <server> <port> (default = 1099)      *
 ***********************************************************/

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <netdb.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <arpa/inet.h>
#include <netinet/in.h>

#include "crypt.h"

/* debug flag */
#undef DEBUG

/* the key */
#define KEY 'P'

/* default port to use */
#define DEFPORT 1099
/* max length of line */
#define MAXLINE 128
/* request string */
#define REQUEST_STRING "getload\n"
/* reply pattern */
#define REPLY_PATTERN "myload %f\n"

/* uptime commando */
#define TMPFILE "/tmp/uptime"
#define UPTIMECMD "/bin/uptime > " TMPFILE

/***********************************************************
 *                                                         *
 * Function:                                               *
 * void usage(char* name)                                  *
 * print usage message                                     *
 * Parameters:                                             * 
 *  name - name of executable                              *
 * Return:                                                 *
 *  -                                                      *
 *                                                         *
 ***********************************************************/

void usage(char* name) {
    printf("%s - a load client\n", name);
    printf("Usage: %s <server> <port> (default port = %d)\n", name, DEFPORT);
    exit(1);
}
 
/***********************************************************
 *                                                         *
 * Function:                                               *
 * double getload(void)                                    *
 * returns current system load                             *
 * Parameters:                                             * 
 *  -                                                      *
 * Return:                                                 *
 *  double - system load                                   *
 *                                                         *
 ***********************************************************/

double getload(void) {
    
    FILE* file;
    int ret;
    char buffer[MAXLINE];
    double load1, load2, load3;
    
    ret = system(UPTIMECMD);
    if (ret == -1) {
        perror("system() Error");
        return (-1);
    }
    
    file = fopen(TMPFILE, "r");
    if (file == NULL) {
        perror("fopen() error");
        return (-1);
    }
    fgets(buffer, sizeof(buffer), file);
    ret = sscanf(&buffer[(strlen(buffer)-17)],
            "%lf, %lf, %lf", &load1, &load2, &load3);
    if (ret != 3) {
        fprintf(stderr, "Format error\n");
        return (-1);
    }

    return load1;

}
    
int main(int argc, char** argv) {
    
    char* server;			/* server string */
    int sock;				/* connection socket */
    int port = DEFPORT;			/* port to use */
    struct sockaddr_in servaddr;	/* server address */
    struct hostent* he;			/* hostentry for DNS resolving */
    int ret;				/* generic return value */
    char plain[MAXLINE];		/* buffer for I/O */
    char cipher[MAXLINE];		/* buffer for I/O */

    /* check for server & port */
    if (argc == 3) {
	server = argv[1];
	port = atoi(argv[2]);
    } else if (argc == 2) {
	server = argv[1];
    } else {
	usage(argv[0]);
    }
    
#ifdef DEBUG
    fprintf(stderr, "Trying connection to %s, %d\n", server, port);
#endif

    /* open connect socket */
    sock = socket(AF_INET, SOCK_STREAM, 0);
    if (sock == -1) {
	perror("Can't open lsocket");
	exit(1);
    }
    
    /* resolve name */
    he = gethostbyname(server);
    if (he == NULL) {
	printf("Canīt resolve %s\n", server);
	exit(0);
    }
    memcpy(&servaddr.sin_addr.s_addr, he->h_addr, sizeof(struct in_addr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(port);
    
#ifdef DEBUG
    fprintf(stderr, "Resolved %s -> %s\n", server,
	    inet_ntoa(servaddr.sin_addr));
#endif

    ret = connect(sock, (struct sockaddr*)&servaddr, sizeof(servaddr));
    if (ret == -1) {
	perror("Can't connect to server");
	exit(1);
    }
    
    printf("Connected to %s\n", inet_ntoa(servaddr.sin_addr));

    /* endless loop */
    while (1) {
	
	if (read(sock, cipher, MAXLINE) == 0) {
	    printf("Server closed connection !\n");
	    close(sock);
	    exit(1);
	}
	
#ifdef DEBUG
	fprintf(stderr, "Read %s from server\n", cipher);
#endif

	decrypt(KEY, cipher, plain);

#ifdef DEBUG
	fprintf(stderr, "%s after decode\n", plain);
#endif


	if (strcmp(plain, REQUEST_STRING)) {
	    fprintf(stderr, "Protocol error - ignoring ! \n");
	    continue;
	}

#ifdef DEBUG
	fprintf(stderr, REPLY_PATTERN, getload());
#endif

	sprintf(plain, REPLY_PATTERN, getload());
	encrypt(KEY, plain, cipher);
	write(sock, cipher, strlen(cipher));

    }

}
