diff options
author | Nate Straz <nstraz@redhat.com> | 2005-09-13 15:48:30 +0000 |
---|---|---|
committer | Nathan Straz <nstraz@redhat.com> | 2008-09-23 09:37:44 -0400 |
commit | c38e0fba0a10d5af0bb25f674177cb6404f73991 (patch) | |
tree | 9e77bcfd7b48187972a951f9cd1a08351d7f01bf /btime/btimed.c | |
parent | 89f8670f4e60cfafbb153bef681b6ada593ea626 (diff) | |
download | qarsh-c38e0fba0a10d5af0bb25f674177cb6404f73991.tar.gz qarsh-c38e0fba0a10d5af0bb25f674177cb6404f73991.tar.xz qarsh-c38e0fba0a10d5af0bb25f674177cb6404f73991.zip |
Copy btime and qarsh over from sistina-test tree
Diffstat (limited to 'btime/btimed.c')
-rw-r--r-- | btime/btimed.c | 271 |
1 files changed, 271 insertions, 0 deletions
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; +} |