#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>

#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>

char *def_host = "localhost";
char *def_port = "9999";
char abuf[INET6_ADDRSTRLEN];

int get_sock_fd(char* host, char* service)
{
	struct addrinfo hints;
	struct addrinfo *result, *rp;
	char *hst, *prt;
	int sock;
	int err;

	hst = host;
	if (!hst)
		hst = def_host;
	prt = service;
	if (!prt)
		prt = def_port;

	memset(&hints, 0, sizeof(struct addrinfo));
	hints.ai_family = AF_UNSPEC;
	hints.ai_socktype = SOCK_STREAM;
	hints.ai_flags = 0;
	hints.ai_protocol = 0;

	printf("Resolving [%s]:%s... ", hst, prt);
	fflush(stdout);
	err = getaddrinfo(hst, prt, &hints, &result);
	if (err) {
		fprintf(stderr, "failed: %s\n", gai_strerror(err));
		sock = -1;
		goto __exit;
	}
	printf("Ok\n");

	for (rp = result; rp; rp = rp->ai_next) {

		void *ap;
		int port;

		switch (rp->ai_family) {

			case AF_INET: {
				struct sockaddr_in *sin = (struct sockaddr_in*)rp->ai_addr;
				ap = (void*)&sin->sin_addr;
				port = sin->sin_port;
			} break;

			case AF_INET6: {
				struct sockaddr_in6 *sin = (struct sockaddr_in6*)rp->ai_addr;
				ap = (void*)&sin->sin6_addr;
				port = sin->sin6_port;
			} break;

			default:
				continue;
		}

		memset(abuf, 0, INET6_ADDRSTRLEN);
		printf("Trying [%s]:%d... ", 
			inet_ntop(rp->ai_family, ap, abuf, INET6_ADDRSTRLEN),
			ntohs(port)
		);
		fflush(stdout);

		sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
		if (-1 == sock) {
			fprintf(stderr, "failed: %s\n", strerror(errno));
			continue;
		};
		err = connect(sock, rp->ai_addr, rp->ai_addrlen);
		if (-1 == err) {
			fprintf(stderr, "failed: %s\n", strerror(errno));
			close(sock);
			continue;
		}
		printf("Ok, connected.\n");
		break;
	}

	if (!rp)
		sock = -1;

	freeaddrinfo(result);

      __exit:
	return sock;
}

char buf[2048];

void gds_ask(int fd, char *cmd)
{
	int r;
	char c;
	int k;

	printf("TX: %s", cmd); 
	r = write(fd, cmd, strlen(cmd));
	if (-1 == r) {
		perror("write()");
		exit(1);
	};

	memset(buf, 0, sizeof(buf));
	k = 0;

	do {
		r = read(fd, &c, 1);
		if (-1 == r) {
			perror("read()");
			break;
		};
		buf[k++] = c;

		if (k == sizeof(buf))
			break;

	} while (c != '\n');

	printf("RX: %s", buf); 
}

int main(int argc, char *argv[])
{
	int fd;

	if (1 == argc) {
		printf("Usage: %s host [service]\n", argv[0]);
		exit(0);
	};

	/* argv[1] - host, argv[2] - service */
	fd = get_sock_fd(argv[1], argv[2]);
	if (-1 == fd)
		exit(1);

	gds_ask(fd, "*idn?\n");

	close(fd);
	exit(0);
}