#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
#include <unistd.h>
#include <getopt.h>
#include <time.h>
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)
{ .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:vq";
+ char short_options[] = "j:c:l:p:dvq";
while (1) {
c = getopt_long(argc, argv, short_options, long_options,
trace_level--;
break;
+ case 'd':
+ opts->daemonize = 1;
+ break;
+
+ case 'p':
+ opts->pid_file = optarg;
+ break;
+
case '?':
return -1;
}
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;
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();