#include "mt.h"
#include <rpc/rpc.h>
#include <errno.h>
#include <sys/poll.h>
#include <rpc/nettype.h>
#include <netdir.h>
#include <stdio.h>
extern int __rpc_timeval_to_msec();
#ifdef DEBUG
#define debug(msg) t_error(msg)
#else
#define debug(msg)
#endif
#define NYEARS (1970 - 1900)
#define TOFFSET ((uint_t)60*60*24*(365*NYEARS + (NYEARS/4)))
int
rtime_tli(char *host, struct timeval *timep, struct timeval *timeout)
{
uint32_t thetime;
int flag;
struct nd_addrlist *nlist = NULL;
struct nd_hostserv rpcbind_hs;
struct netconfig *nconf = NULL;
int foundit = 0;
int fd = -1;
nconf = __rpc_getconfip(timeout == NULL ? "tcp" : "udp");
if (nconf == NULL)
goto error;
if ((fd = t_open(nconf->nc_device, O_RDWR, NULL)) == -1) {
debug("open");
goto error;
}
if (t_bind(fd, NULL, NULL) < 0) {
debug("bind");
goto error;
}
rpcbind_hs.h_host = host;
rpcbind_hs.h_serv = "time";
if (netdir_getbyname(nconf, &rpcbind_hs, &nlist))
goto error;
if (nconf->nc_semantics == NC_TPI_CLTS) {
struct t_unitdata tu_data;
struct pollfd pfd;
int res;
int msec;
tu_data.addr = *nlist->n_addrs;
tu_data.udata.buf = (char *)&thetime;
tu_data.udata.len = (uint_t)sizeof (thetime);
tu_data.udata.maxlen = tu_data.udata.len;
tu_data.opt.len = 0;
tu_data.opt.maxlen = 0;
if (t_sndudata(fd, &tu_data) == -1) {
debug("udp");
goto error;
}
pfd.fd = fd;
pfd.events = POLLIN | POLLPRI | POLLRDNORM | POLLRDBAND;
msec = __rpc_timeval_to_msec(timeout);
do {
res = poll(&pfd, 1, msec);
} while (res < 0);
if ((res <= 0) || (pfd.revents & POLLNVAL))
goto error;
if (t_rcvudata(fd, &tu_data, &flag) < 0) {
debug("udp");
goto error;
}
foundit = 1;
} else {
struct t_call sndcall;
sndcall.addr = *nlist->n_addrs;
sndcall.opt.len = sndcall.opt.maxlen = 0;
sndcall.udata.len = sndcall.udata.maxlen = 0;
if (t_connect(fd, &sndcall, NULL) == -1) {
debug("tcp");
goto error;
}
if (t_rcv(fd, (char *)&thetime, (uint_t)sizeof (thetime), &flag)
!= (uint_t)sizeof (thetime)) {
debug("tcp");
goto error;
}
foundit = 1;
}
thetime = ntohl(thetime);
timep->tv_sec = thetime - TOFFSET;
timep->tv_usec = 0;
error:
if (nconf) {
(void) freenetconfigent(nconf);
if (fd != -1) {
(void) t_close(fd);
if (nlist)
netdir_free((char *)nlist, ND_ADDRLIST);
}
}
return (foundit);
}