/* c-tcp-client -- establishes a tcp socket connection (client) */
/* $Id$ */
/* Carlos Duarte <cgd@teleweb.pt>, 000425 */

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

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

/* for NONBLOCK */
#include <unistd.h>
#include <fcntl.h>


static void die(char *msg,...)
{
	if (msg) {
		va_list av; 
		va_start(av,msg);
		vfprintf(stderr, msg, av); 
		fprintf(stderr, "\n"); 
		va_end(av);
	}
	exit(2); 
}

int main(int argc, char *argv[]) 
{
	char *hostname; 
	unsigned short port; 
	struct sockaddr_in sock; 
	int sd; 

	if (argc != 3)
		die("usage: %s host port", argv[0]); 

	hostname = argv[1]; 
	port = atoi(argv[2]); 
	if (port == 0)
		die("%s: bad port", argv[2]); 

	/* converts host:port into a struct sockaddr_in */
	sock.sin_family = AF_INET; 
	sock.sin_port = htons(port); 
	if (!inet_aton(hostname, &sock.sin_addr)) {
		struct hostent *h = gethostbyname(hostname); 
		if (!h) 
			die("can't resolv %s:", hostname); 
		/* sin_addr has one member only: sin_addr.s_addr */
		memcpy(&sock.sin_addr, h->h_addr, sizeof(sock.sin_addr)); 
	}

	fprintf(stderr, "Trying %s:%d... \n", 
		inet_ntoa(sock.sin_addr), ntohs(sock.sin_port)); 

	/* creates the socket fd and start the connection */
	if ((sd = socket(PF_INET, SOCK_STREAM, 0)) == -1) 
		die("can't creat socket"); 

	/* could retry once or twice if this fails */
	if (connect(sd, &sock, sizeof sock) == -1) 
		die("can't connect"); 

	/* now we're ready to read and write to sd, beware with timeouts */
	if (fcntl(sd, F_SETFL, O_NONBLOCK) == -1) 
		fprintf(stderr, "warning: read/writes will block"); 

	/* read all data from port... */
	{
		char buf[256]; 
		int n; 
		while ((n = read(sd, buf, sizeof buf))>0)
			fwrite(buf, 1, n, stdout); 
		if (n== -1 && errno != EAGAIN)
			perror("read"); 
	}
	close(sd); 
	return(0); 
}
