*
 * Usage: get_time hostname [nodename] run in CTOS Read time
 * from host name expressed in seconds since January 1, 1900
 * and repeat 10 times
 *

include <systypes.h>
include <syssocket.h>
include <netinetin.h>
include <netdb.h>
include <arpainet.h>
include <errno.h>


define BUFSZ 			512
define TIMEPORT    	37		* time service port *
define MYPORT      	0
define TIMERVAL		80		* set timer value to 8 sec.
								 * for recvfrom *
define REXMIT          10		* number of retransmissions *



extern int      PlmFar(Delay) (int n);
extern char    *SockAddrStr(struct sockaddr_in * saddr);


*
 * FORWARD REFERENCES
 *
void            CheckP(int, char *);
char           *SockAddrStr(struct sockaddr_in * saddr);


int             s;				* file descriptor returned by
								 * socket call  *
int             n;				* return value of function
								 * calls           *
struct sockaddr_in server;		* server socket address *
struct sockaddr_in myaddr;		* local address  *
struct hostent *hp;				* pointer to structure
								 * containing host address *
char            inbuff[BUFSZ];	* input buffer *
char           *sendbuf = what time do you have?;
char           *nodename = local;



main(int argc, char *argv[])
***************************
 *  argv[0] = program name
 *  argv[1] = host name
 *  argv[2] = nodename
 ***************************
{
	int             i,
	                serverAddrLen;
	unsigned long   timeval,
	                timebuf;
	unsigned long   seconds,
	                hours,
	                minutes;

	if (argc < 2 || argc > 3) {	* verify correct number of
								 * args *
		printf(usage: get_time hostname [nodename]\n);
		exit(0);
	}

	*
	 * AF_INET is communications domain, SOCK_DGRAM specifies
	 * the type of communications IPPROTO_UDP represents the
	 * protocol to be used.
	 *

	if (argc >= 3)
		nodename = argv[2];

	n = setctosparams(nodename, 0);
	CheckP(n, set ctos params\n);

	s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
	CheckP(s, socket);

	n = setctosudpparams(s, NULL, TIMERVAL, 0);
	CheckP(n, set udp params\n);


	hp = gethostbyname(local);
	if (hp == NULL) {
		printf(invalid host argument = local\n);
		exit(1);
	}
	CheckP((hp == NULL ? 1 : 0), gethostbyname for local host);
	memcpy((char *) server.sin_addr.s_addr, hp>h_addr, hp>h_length);

	myaddr.sin_family = AF_INET;
	myaddr.sin_addr.s_addr = htonl(INADDR_ANY);
	myaddr.sin_port = htons(MYPORT);
	memcpy(myaddr.sin_addr.s_addr, hp>h_addr, hp>h_length);
	n = bind(s, myaddr, sizeof(myaddr));
	CheckP(n, BIND);


	server.sin_family = AF_INET;* assign domain *
	server.sin_port = htons(TIMEPORT);	* assign remote port *

	*
	 * take the host name entered as an argument to this
	 * program and uses it to get the address of the remote
	 * host we connect to.
	 *
	hp = gethostbyname(argv[1]);
	if (hp == NULL) {
		printf(invalid host argument = s\n, argv[1]);
		exit(1);
	}
	CheckP((hp == NULL ? 1 : 0), gethostbyname for servers host);
	memcpy((char *) server.sin_addr.s_addr, hp>h_addr, hp>h_length);
	serverAddrLen = sizeof(server);


	printf(Local address : s\n, SockAddrStr(myaddr));
	printf(Server address: s\n, SockAddrStr(server));


	for (i = 1; i < REXMIT + 1; i++) {
		n = recvfrom(s, (char *) timebuf, 4, 
					MSG_NOBLOCK | MSG_POSTREQ, 
					server, serverAddrLen);

		if (n < 0)
			if (errno = EWOULDBLOCK)
				CheckP(n, nonblocking recvfrom\n);

		n = sendto(s, sendbuf, 21, 0, server, serverAddrLen);
		CheckP(n, sendto: requesting time);

		n = recvfrom(s, (char *) timebuf, 4, 0, server, serverAddrLen);
		if (n < 0) {
			if (errno = E_TIMEOUT)
				CheckP(n, recvfrom: waiting response\n);
			else
				printf(recvfrom timeout in count d\n, i);
		} else {
			timeval = ntohl(timebuf);
			seconds = timeval  (long) 86400L;
			hours = seconds  3600;
			hours = (hours + 19)  24;	* GMT to EST *
			seconds = seconds  3600;
			minutes = seconds  60;
			seconds = seconds  60;

			printf(request d to remote host\n, i);
			printf(time from s is lu:2.2lu:2.2lu\n,
				   argv[1], hours, minutes, seconds);
			Delay(20);
		}

	}

	sclose(s);
	return 0;

}								* end main *


void
CheckP(int n, char *msg)
**************
 * if n is positive return quietly
 * else display msg  quit
 *
{
	if (n < 0) {
		printf( Program terminated: error u in s\n, errno, msg);
		exit(1);
	} else {
ifdef DEBUG
		printf(s successful\n, msg);
endif
	}
}


char           *
SockAddrStr(struct sockaddr_in * saddr)
**************************************
 * Convert a sockaddr_in structure to
 * a printable string of the form
 * (255.255.255.255, 9999)
 * where; 255.255.255.255 is the 
 * host address, and
 * 9999 is the port number
 *
{
	static          saddr_fmt[40];

	if (saddr>sin_family == AF_INET)
		sprintf(saddr_fmt, (s, d),
		 inet_ntoa(saddr>sin_addr), ntohs(saddr>sin_port));
	else
		saddr_fmt[0] = 0;
	return saddr_fmt;
}
