summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/daemon.c52
-rw-r--r--src/dnscap.1.in3
-rw-r--r--src/options.c11
-rw-r--r--src/options.h4
4 files changed, 70 insertions, 0 deletions
diff --git a/src/daemon.c b/src/daemon.c
index 88ce785..596b863 100644
--- a/src/daemon.c
+++ b/src/daemon.c
@@ -224,6 +224,57 @@ void drop_privileges(void)
#endif
}
+void write_pid_file(void)
+{
+ FILE* fp;
+ int fd, flags;
+ struct flock lock;
+
+ if (!options.pid_file)
+ return;
+
+ if ((fd = open(options.pid_file, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR)) == -1) {
+ fprintf(stderr, "unable to open PID file %s: %s", options.pid_file, strerror(errno));
+ exit(1);
+ }
+
+ if ((flags = fcntl(fd, F_GETFD)) == -1) {
+ fprintf(stderr, "unable to get PID file flags: %s", strerror(errno));
+ exit(1);
+ }
+ flags |= FD_CLOEXEC;
+ if (fcntl(fd, F_SETFD, flags) == 1) {
+ fprintf(stderr, "unable to set PID file flags: %s", strerror(errno));
+ exit(1);
+ }
+
+ lock.l_type = F_WRLCK;
+ lock.l_whence = SEEK_SET;
+ lock.l_start = 0;
+ lock.l_len = 0;
+
+ if (fcntl(fd, F_SETLK, &lock) == -1) {
+ if (errno == EACCES || errno == EAGAIN) {
+ fprintf(stderr, "PID file locked by other process");
+ exit(1);
+ }
+
+ fprintf(stderr, "unable to lock PID file: %s", strerror(errno));
+ exit(1);
+ }
+
+ if (ftruncate(fd, 0) == -1) {
+ fprintf(stderr, "unable to truncate PID file: %s", strerror(errno));
+ exit(1);
+ }
+
+ fp = fdopen(fd, "w");
+ if (!fp || fprintf(fp, "%d\n", getpid()) < 1 || fflush(fp)) {
+ fprintf(stderr, "unable to write to PID file: %s", strerror(errno));
+ exit(1);
+ }
+}
+
void daemonize(void)
{
pid_t pid;
@@ -235,6 +286,7 @@ void daemonize(void)
exit(1);
} else if (pid > 0)
exit(0);
+ write_pid_file();
openlog("dnscap", 0, LOG_DAEMON);
if (setsid() < 0) {
logerr("setsid failed: %s", strerror(errno));
diff --git a/src/dnscap.1.in b/src/dnscap.1.in
index f33fcfc..58c4b90 100644
--- a/src/dnscap.1.in
+++ b/src/dnscap.1.in
@@ -163,6 +163,9 @@ functions, unless options
.B \-N
is given or only reading from files.
.TP
+.BI "\-o pid_file" =...
+Specify the file to write the PID to when running as a daemon (default none).
+.TP
.BI "\-o user" =...
Specify the user to drop privileges to (default nobody).
.TP
diff --git a/src/options.c b/src/options.c
index 29a5dad..8d03c26 100644
--- a/src/options.c
+++ b/src/options.c
@@ -228,6 +228,13 @@ int option_parse(options_t* options, const char* option)
options->bpf_hosts_apply_all = 1;
return 0;
}
+ } else if (have("pid_file")) {
+ if (options->pid_file) {
+ free(options->pid_file);
+ }
+ if ((options->pid_file = strdup(argument))) {
+ return 0;
+ }
}
return 1;
@@ -244,5 +251,9 @@ void options_free(options_t* options)
free(options->group);
options->group = 0;
}
+ if (options->pid_file) {
+ free(options->pid_file);
+ options->pid_file = 0;
+ }
}
}
diff --git a/src/options.h b/src/options.h
index 40e0ee8..99acb8d 100644
--- a/src/options.h
+++ b/src/options.h
@@ -72,6 +72,8 @@ enum dump_format {
\
0, 0, 0, 0, 0, \
\
+ 0, \
+\
0 \
}
@@ -113,6 +115,8 @@ struct options {
int reassemble_tcp_bfbparsedns;
int bpf_hosts_apply_all;
+
+ char* pid_file;
};
int option_parse(options_t* options, const char* option);