]> git.itanic.dy.fi Git - rrdd/blobdiff - main.c
onewire_parser.c: Fix compiler warnings about string lengths
[rrdd] / main.c
diff --git a/main.c b/main.c
index 55e1ef3fc046f349aecffa4adce7f987cb792762..d57fb0b646b36983d67da88a08cc2068435c5a78 100644 (file)
--- a/main.c
+++ b/main.c
@@ -1,4 +1,6 @@
 #include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
 #include <unistd.h>
 #include <getopt.h>
 #include <time.h>
@@ -16,7 +18,9 @@
 
 struct user_options {
        int max_jobs;
+       int daemonize;
        char *config_file;
+       char *pid_file;
 };
 
 int read_args(int argc, char *argv[], struct user_options *opts)
@@ -26,9 +30,13 @@ int read_args(int argc, char *argv[], struct user_options *opts)
                { .val = 'j', .has_arg = 1, .name = "jobs", },
                { .val = 'c', .has_arg = 1, .name = "config", },
                { .val = 'l', .has_arg = 1, .name = "log-file", },
+               { .val = 'p', .has_arg = 1, .name = "pid-file", },
+               { .val = 'd', .name = "daemon", },
+               { .val = 'v', .name = "verbose", },
+               { .val = 'q', .name = "quiet", },
                { },
        };
-       char short_options[] = "j:c:l:";
+       char short_options[] = "j:c:l:p:dvq";
 
        while (1) {
                c = getopt_long(argc, argv, short_options, long_options,
@@ -50,6 +58,22 @@ int read_args(int argc, char *argv[], struct user_options *opts)
                        open_log_file(optarg);
                        break;
 
+               case 'v':
+                       trace_level++;
+                       break;
+
+               case 'q':
+                       trace_level--;
+                       break;
+
+               case 'd':
+                       opts->daemonize = 1;
+                       break;
+
+               case 'p':
+                       opts->pid_file = optarg;
+                       break;
+
                case '?':
                        return -1;
                }
@@ -63,6 +87,73 @@ int read_args(int argc, char *argv[], struct user_options *opts)
        return 0;
 }
 
+static int is_already_running(const char *pidfile)
+{
+       struct stat s;
+       char pidstr[16], procpath[256] = { 0 };
+       int fd, ret, pid;
+
+       fd = open(pidfile, O_RDONLY);
+       if (fd < 0) {
+               /* No pid, no running instance */
+               return 0;
+       }
+
+       ret = read(fd, pidstr, sizeof(pidstr) - 1);
+       if (ret < 0) {
+               pr_err("Failed to read pid file: %m\n");
+               close(fd);
+
+               return ret;
+       }
+       close(fd);
+
+       pidstr[ret] = 0;
+
+       ret = sscanf(pidstr, "%d", &pid);
+
+       /* Corrupted pid data? Maybe leftover from prev boot or something */
+       if (ret != 1)
+               return 0;
+
+       snprintf(procpath, sizeof(procpath) - 1, "/proc/%d/", pid);
+
+       ret = stat(procpath, &s);
+
+       if (ret < 0) {
+               pr_info("Ignoring stale pid %d from pid file %s\n",
+                       pid, pidfile);
+
+               return 0;
+       }
+
+       pr_err("Process %d is already running as stated in pid file %s\n",
+               pid, pidfile);
+
+       return 1;
+}
+
+static int write_pidfile(const char *pidfile)
+{
+       char pidstr[16];
+       int fd, ret;
+
+       fd = open(pidfile, O_WRONLY | O_CREAT, 0644);
+       if (fd < 0) {
+               pr_err("Failed to open pidfile %s for writing: %m\n", pidfile);
+               return -1;
+       }
+
+       ret = snprintf(pidstr, sizeof(pidstr), "%d", getpid());
+       ret = write(fd, pidstr, ret);
+       if (ret < 0)
+               pr_err("Failed to write to pidfile %s: %m\n", pidfile);
+
+       close(fd);
+
+       return ret;
+}
+
 int main(int argc, char *argv[])
 {
        struct user_options opts;
@@ -77,8 +168,26 @@ int main(int argc, char *argv[])
        if (read_args(argc, argv, &opts) < 0)
                return -1;
 
+       if (opts.daemonize) {
+               pr_info("Setting itself as a daemon\n");
+               ret = daemon(1, 0);
+               if (ret < 0) {
+                       pr_err("Failed to daemonize: %m\n");
+                       return -1;
+               }
+       }
+
+       if (opts.pid_file) {
+               if (is_already_running(opts.pid_file))
+                       return -1;
+
+               if (write_pidfile(opts.pid_file) < 0)
+                       return -1;
+       }
+
        init_plugin_manager(argv[0]);
        register_built_in_parsers();
+       register_network_parser();
 
        if (!opts.config_file) {
                pr_err("No database config file given. Nothing to do\n");
@@ -101,7 +210,6 @@ int main(int argc, char *argv[])
                char timestr[128];
                time_t t;
 
-               pr_info("loop start\n");
                /*
                 * Update all databases parallel in one shot
                 */
@@ -110,10 +218,13 @@ int main(int argc, char *argv[])
 
                sleeptime = get_next_update(db_list, &db_name);
 
-               t = time(0) + sleeptime;
-               strftime(timestr, sizeof(timestr), "%T", localtime(&t));
-               pr_info("Next scheduled event \"%s\" at %s, in %d seconds\n",
-                       db_name, timestr, sleeptime);
+               if (sleeptime >=  0) {
+                       t = time(0) + sleeptime;
+                       strftime(timestr, sizeof(timestr), "%T", localtime(&t));
+                       pr_info("Next scheduled event \"%s\" at %s, in %d seconds\n",
+                               db_name, timestr, sleeptime);
+               } else
+                       pr_info("All jobs active, sleeping until event arrives\n");
 
                poll_job_requests(sleeptime);
        }