summaryrefslogtreecommitdiffstats
path: root/btimed.c
diff options
context:
space:
mode:
authorNate Straz <nstraz@redhat.com>2005-09-13 16:01:28 +0000
committerNathan Straz <nstraz@redhat.com>2008-09-23 09:37:44 -0400
commitbf489daffc4902db3a9eb95d485fd867ac1ea524 (patch)
treec022f12c9d1bb8b56b566976cf5127b37112bbf1 /btimed.c
parentc38e0fba0a10d5af0bb25f674177cb6404f73991 (diff)
downloadqarsh-bf489daffc4902db3a9eb95d485fd867ac1ea524.tar.gz
qarsh-bf489daffc4902db3a9eb95d485fd867ac1ea524.tar.xz
qarsh-bf489daffc4902db3a9eb95d485fd867ac1ea524.zip
Flatten the qarsh tree.
Diffstat (limited to 'btimed.c')
-rw-r--r--btimed.c271
1 files changed, 271 insertions, 0 deletions
diff --git a/btimed.c b/btimed.c
new file mode 100644
index 0000000..259c8aa
--- /dev/null
+++ b/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;
+}