summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNate Straz <nstraz@redhat.com>2005-09-13 15:48:30 +0000
committerNathan Straz <nstraz@redhat.com>2008-09-23 09:37:44 -0400
commitc38e0fba0a10d5af0bb25f674177cb6404f73991 (patch)
tree9e77bcfd7b48187972a951f9cd1a08351d7f01bf
parent89f8670f4e60cfafbb153bef681b6ada593ea626 (diff)
downloadqarsh-c38e0fba0a10d5af0bb25f674177cb6404f73991.zip
qarsh-c38e0fba0a10d5af0bb25f674177cb6404f73991.tar.gz
qarsh-c38e0fba0a10d5af0bb25f674177cb6404f73991.tar.xz
Copy btime and qarsh over from sistina-test tree
-rw-r--r--btime/Makefile48
-rw-r--r--btime/btime.c111
-rw-r--r--btime/btime.h10
-rw-r--r--btime/btime_int.h12
-rw-r--r--btime/btimec.c28
-rw-r--r--btime/btimed.c271
6 files changed, 480 insertions, 0 deletions
diff --git a/btime/Makefile b/btime/Makefile
new file mode 100644
index 0000000..6a2a454
--- /dev/null
+++ b/btime/Makefile
@@ -0,0 +1,48 @@
+include ../../make/defines.mk
+
+.PHONY: clean clobber uninstall
+
+CC = gcc
+AR = ar
+#CFLAGS += -g
+
+all: libbtime.a btimed btimec
+
+btimed: btimed.c btime_int.h
+ $(CC) $(CFLAGS) -o btimed btimed.c
+
+btimec: btimec.c libbtime.a
+ $(CC) $(CFLAGS) -L. -o btimec btimec.c -lbtime
+
+libbtime.a: btime.c btime_int.h
+ $(CC) $(CFLAGS) -c btime.c
+ $(AR) -rc libbtime.a btime.o
+
+install: btimed btimec libbtime.a
+ @echo "Installing btime deamon and test client"
+ @install -d ${STSDIR}/bin/
+ @install btimed ${STSDIR}/bin
+ @install btimec ${STSDIR}/bin
+
+ @echo "Installing btime library"
+ @install -d ${STSDIR}/lib/
+ @install libbtime.a ${STSDIR}/lib
+
+ @echo "Installing btime header"
+ @install -d ${STSDIR}/include/
+ @install btime.h ${STSDIR}/include
+
+
+uninstall:
+ ${UNINSTALL} btimed ${STSDIR}/bin
+ ${UNINSTALL} btimec ${STSDIR}/bin
+
+
+clean:
+ /bin/rm -f *.o
+
+clobber:
+ /bin/rm -f btimec
+ /bin/rm -f btimed
+ /bin/rm -f *.a *.o
+
diff --git a/btime/btime.c b/btime/btime.c
new file mode 100644
index 0000000..f22c08b
--- /dev/null
+++ b/btime/btime.c
@@ -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;
+}
diff --git a/btime/btime.h b/btime/btime.h
new file mode 100644
index 0000000..41d3e39
--- /dev/null
+++ b/btime/btime.h
@@ -0,0 +1,10 @@
+/*
+ * btime.h --
+ */
+
+#ifndef __BTIME_H
+#define __BTIME_H
+
+extern unsigned int btime(const char *host);
+
+#endif /* __BTIME_H */
diff --git a/btime/btime_int.h b/btime/btime_int.h
new file mode 100644
index 0000000..b2cafcd
--- /dev/null
+++ b/btime/btime_int.h
@@ -0,0 +1,12 @@
+/*
+ * btime_int.h --
+ */
+
+#ifndef __BTIME_INT_H
+#define __BTIME_INT_H
+
+#define BTIME_PORT 23456
+#define BTIME_MSGLEN 128
+#define MAX_RETRY 5
+
+#endif /* __BTIME_INT_H */
diff --git a/btime/btimec.c b/btime/btimec.c
new file mode 100644
index 0000000..02c29bc
--- /dev/null
+++ b/btime/btimec.c
@@ -0,0 +1,28 @@
+/*
+ * btimec.c --
+ *
+ * Example program for libbtime
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "btime.h"
+
+int
+main(int argc, char **argv)
+{
+ unsigned int bt;
+ char *btimedhost;
+
+ if (argc != 2) {
+ fprintf(stderr, "USAGE: %s <host>\n", argv[0]);
+ exit(2);
+ }
+
+ btimedhost = argv[1];
+ bt = btime(btimedhost);
+ printf("%s: %u\n", btimedhost, bt);
+
+ exit(0);
+}
diff --git a/btime/btimed.c b/btime/btimed.c
new file mode 100644
index 0000000..259c8aa
--- /dev/null
+++ b/btime/btimed.c
@@ -0,0 +1,271 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <errno.h>
+#include <signal.h>
+#include <syslog.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include "btime_int.h"
+
+static void (*btimed_error)(int level, const char *fmt, ...);
+
+static void btimed(void);
+static unsigned int get_btime(void);
+static int daemon_init(void);
+static void btimed_perror(int level, const char *fmt, ...);
+static void sigchld_hdlr(int sig);
+static void usage(const char *progname);
+
+
+int
+main(int argc, char **argv)
+{
+ struct sigaction sa;
+ int debug = 0;
+ int c;
+
+ while ((c = getopt(argc, argv, "hd")) != -1) {
+ switch (c) {
+ case 'd':
+ debug = 1;
+ break;
+ case 'h':
+ case '?':
+ default:
+ usage(argv[0]);
+ exit(2);
+ }
+ }
+
+ memset(&sa, 0, sizeof(sa));
+ sa.sa_handler = sigchld_hdlr;
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = SA_NOCLDSTOP | SA_RESTART;
+ sigaction(SIGCHLD, &sa, NULL);
+
+ if (debug) {
+ btimed_error = btimed_perror;
+ } else {
+ btimed_error = syslog;
+ daemon_init();
+ }
+
+ btimed();
+
+ return 0;
+}
+
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * btimed --
+ *
+ * The main loop of the deamon. It listens on its well know port for
+ * messages, responds to the request via a child process.
+ *
+ * Returns:
+ * Never returns.
+ *
+ * Side effects:
+ * Child processes are created.
+ *---------------------------------------------------------------------------
+ */
+
+static void
+btimed(void)
+{
+ int sd;
+ char msg[BTIME_MSGLEN];
+ struct sockaddr_in cli_addr;
+ int cli_addr_len;
+ struct sockaddr_in my_addr;
+ pid_t pid;
+ ssize_t nbytes;
+
+ if ((sd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+ btimed_error(LOG_ERR, "Could not create socket: %s\n",
+ strerror(errno));
+ exit(1);
+ }
+
+ 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(BTIME_PORT);
+ if (bind(sd, (struct sockaddr *)&my_addr, sizeof my_addr) < 0) {
+ btimed_error(LOG_ERR, "Could not bind to local address: %s\n",
+ strerror(errno));
+ exit(1);
+ }
+
+ for (;;) {
+ memset(&cli_addr, 0, sizeof cli_addr);
+ cli_addr_len = sizeof cli_addr;
+ nbytes = recvfrom(sd, &msg, BTIME_MSGLEN, MSG_WAITALL,
+ (struct sockaddr *)&cli_addr, &cli_addr_len);
+
+ if ((pid = fork()) < 0) {
+ btimed_error(LOG_ERR, "Could not fork(): %s\n", strerror(errno));
+ exit(1);
+ }
+
+ if (pid == 0) {
+ memset(msg, 0, BTIME_MSGLEN);
+ sprintf(msg, "%u\n", get_btime());
+ sendto(sd, &msg, BTIME_MSGLEN, MSG_DONTWAIT,
+ (struct sockaddr *)&cli_addr, cli_addr_len);
+
+ exit(0);
+ }
+ }
+
+ close(sd);
+}
+
+
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * get_btime --
+ *
+ * Return machine's boot time.
+ *
+ * Returns:
+ * 0 on failure
+ * non-zero on success.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static unsigned int
+get_btime(void)
+{
+ FILE *statf;
+ char line[1024];
+ unsigned int btime = 0;
+
+ if ((statf = fopen("/proc/stat", "r")) == NULL) {
+ btimed_error(LOG_ERR, "/proc/stat open failure: %s\n",
+ strerror(errno));
+ exit(1);
+ }
+
+ while (fgets(line, 1024, statf) != NULL) {
+ if (strstr(line, "btime") != NULL) {
+ sscanf(line, "%*s%u", &btime);
+ }
+
+ }
+
+ fclose(statf);
+
+ return btime;
+}
+
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * daemon_init --
+ *
+ * Set up a basic daemon environment
+ *
+ * Returns:
+ * 0 on success
+ * non-zero on failure.
+ *
+ * Side effects:
+ * All fds are closed and process is now a session leader.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static int
+daemon_init(void)
+{
+ pid_t pid;
+ int fd;
+ int maxfd = sysconf(_SC_OPEN_MAX);
+
+ if ((pid = fork()) < 0) {
+ return(-1);
+ } else if (pid != 0) {
+ exit(0); /* Exit in parent */
+ }
+
+ /*
+ * Child sets up daemon environment
+ */
+
+ setsid(); /* Become session leader */
+ chdir("/");
+ umask(0);
+ for (fd = 0; fd < maxfd; fd++) {
+ close(fd);
+ }
+ errno = 0; /* probably set to EBADFD from above loop, reset */
+
+ openlog("btimed", LOG_PID, LOG_USER);
+
+ return 0;
+}
+
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * btimed_perror --
+ *
+ * Print error messages to stderr, level is not used, it is there
+ * to have the same calling args as syslog(3) so we can use either
+ * based on debug level.
+ *
+ * Returns:
+ * NA
+ *
+ * Side effects:
+ * None
+ *---------------------------------------------------------------------------
+ */
+
+static void
+btimed_perror(int level, const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+}
+
+
+static void
+sigchld_hdlr(int sig)
+{
+ int status;
+
+ wait(&status);
+ return;
+}
+
+
+static void
+usage(const char *progname)
+{
+ fprintf(stderr, "Usage: %s [OPTION]...\n"
+ "-h\tPrint this help and exit.\n"
+ "-d\tDon't daemonize, send output to stderr.\n",
+ progname);
+
+ return;
+}