/*
 * Sample program written for BSD-derived UNIX to talk to a device 
 * attached to the serial port on an NCD Network Display Station
 *
 * This program is provide "as-is" by NCD with no warranty as to its
 * fitness for any purpose.
 */
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>

/* for systems that don't have a modern select() */
#ifndef FD_SETSIZE
#define FD_SETSIZE	NOFILE
#endif 

#define BUFSIZE		1024

main(argc, argv)
int argc;
char *argv[];
{
	int sfd, len, on = 1;
	struct sockaddr_in inaddr;
	struct hostent *hp;
	char buf[BUFSIZE];

	/* check number of arguments */
	if (argc != 2) {
		perror(argv[0]);
		exit(1);
	}

	/* create a socket */
	if ((sfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
		fprintf(stderr, "%s: can't open socket\n", argv[0]);
		exit(2);
	}

	/* resolve network address of NCD unit */
	inaddr.sin_family = AF_INET;
	inaddr.sin_port = htons(87);	/* the NCD RS-232 daemon TCP port */
	if ((inaddr.sin_addr.s_addr = inet_addr(argv[1])) == -1) {
		if ((hp = gethostbyname(argv[1])) == NULL
		    || hp->h_addrtype != AF_INET) {
			fprintf(stderr, "%s: can't resolve name %s\n", 
				argv[0], argv[1]);
			exit(3);
		}
		bcopy(hp->h_addr, &inaddr.sin_addr.s_addr, hp->h_length);
	}

	/* connect to NCD RS-232 daemon */
	if (connect(sfd, &inaddr, sizeof(inaddr)) < 0) {
		perror(argv[0]);
		exit(4);
	}

	/* 
	 * do bi-directional I/O until EOF or error 
	 *
	 * The actions on EOF and error should be customized
	 * for the specific device and application. For example,
	 * one might want to continue reading from the network,
	 * even after EOF has been reached on stdin.
	 */
	while (1) {
		fd_set rfds;

		FD_ZERO(&rfds);
		FD_SET(sfd, &rfds);
		FD_SET(0, &rfds);
		if (select(FD_SETSIZE, &rfds, NULL, NULL, NULL) < 0)
			break;

		/* read stdin, write output to network connection */
		if (FD_ISSET(0, &rfds)) {
			if ((len = read(0, buf, sizeof(buf))) > 0)
				write(sfd, buf, len);
			else /* EOF or error */
				break;
		}

		/*
		 * read any messages from the network, and write them to stdout
		 *
		 * Some printers, such as Laserwriters send back logging info.
		 */
		if (FD_ISSET(sfd, &rfds)) {
			if ((len = read(sfd, buf, sizeof(buf))) > 0)
				write(1, buf, len);
			else /* EOF or error */
				break;
		}
	}

	/* clean up */
	exit(0);
}

