diff options
author | Nate Straz <nstraz@redhat.com> | 2005-09-13 16:01:28 +0000 |
---|---|---|
committer | Nathan Straz <nstraz@redhat.com> | 2008-09-23 09:37:44 -0400 |
commit | bf489daffc4902db3a9eb95d485fd867ac1ea524 (patch) | |
tree | c022f12c9d1bb8b56b566976cf5127b37112bbf1 /btime.c | |
parent | c38e0fba0a10d5af0bb25f674177cb6404f73991 (diff) | |
download | qarsh-bf489daffc4902db3a9eb95d485fd867ac1ea524.tar.gz qarsh-bf489daffc4902db3a9eb95d485fd867ac1ea524.tar.xz qarsh-bf489daffc4902db3a9eb95d485fd867ac1ea524.zip |
Flatten the qarsh tree.
Diffstat (limited to 'btime.c')
-rw-r--r-- | btime.c | 111 |
1 files changed, 111 insertions, 0 deletions
@@ -0,0 +1,111 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <fcntl.h> +#include <errno.h> +#include <netdb.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> + +#include "btime_int.h" + +/* + * btime -- + * + * Return the boot time of a remote host if that host is running the + * btimed deamon. + * + * Returns: + * btime, or 0 on failure. + */ + +unsigned int +btime(const char *host) +{ + int sd; + char msg[BTIME_MSGLEN]; + struct sockaddr_in serv_addr; + struct sockaddr_in my_addr; + int serv_addr_len; + struct hostent *hostent; + in_addr_t inaddr; + unsigned int btime; + ssize_t nbytes; + int retry; + + if ((sd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { + fprintf(stderr, "Could not create socket: %s\n", + strerror(errno)); + return 0; + } + + memset(&serv_addr, 0, sizeof serv_addr); + serv_addr.sin_family = AF_INET; + serv_addr.sin_port = htons(BTIME_PORT); + + if ((inaddr = inet_addr(host)) != INADDR_NONE) { + memcpy(&serv_addr.sin_addr, &inaddr, sizeof inaddr); + } else { + if ((hostent = gethostbyname(host)) == NULL) { + return 0; + } + + memcpy(&serv_addr.sin_addr, hostent->h_addr, hostent->h_length); + } + + memset(&my_addr, 0, sizeof my_addr); + my_addr.sin_family = AF_INET; + my_addr.sin_addr.s_addr = htonl(INADDR_ANY); + my_addr.sin_port = htons(0); + if (bind(sd, (struct sockaddr *)&my_addr, sizeof my_addr) < 0) { + fprintf(stderr, "Could not bind to local address: %s\n", + strerror(errno)); + return 0; + } + + memset(msg, 0, BTIME_MSGLEN); + for (retry = 0; retry < MAX_RETRY; retry++) { + serv_addr_len = sizeof serv_addr; + if ((nbytes = sendto(sd, &msg, BTIME_MSGLEN, MSG_DONTWAIT, + (struct sockaddr *)&serv_addr, serv_addr_len)) < 0) { + if (errno == EAGAIN) { + usleep(retry * 100); + } else { + /* Non EAGAIN error... */ + break; + } + } else { + break; + } + } + + + memset(msg, 0, BTIME_MSGLEN); + for (retry = 0; retry < MAX_RETRY; retry++) { + serv_addr_len = sizeof serv_addr; + if ((nbytes = recvfrom(sd, &msg, BTIME_MSGLEN, MSG_DONTWAIT, + (struct sockaddr *)&serv_addr, &serv_addr_len)) < 0) { + if (errno == EAGAIN) { + usleep(retry * 100); + } else { + /* Non EAGAIN error... */ + break; + } + } else { + break; + } + } + + if (nbytes == 0) { + btime = 0; + } else { + btime = strtoul(msg, (char **)NULL, 10); + } + + close(sd); + + return btime; +} |