#include <sys/types.h> /* for pid_t */
#include <sys/stat.h> /* for open */
#include <errno.h> /* for EACCESS and EAGAIN */
#include <stdio.h> /* for snprintf() */
#include <string.h> /* for memset() */
#include <unistd.h> /* for ftruncate() */
#include <fcntl.h> /* for fcntl() */
#include "debug.h"
#include "pidfile.h"
int pidfile_create(const char *pidFile, pid_t pid)
{
char buf[20];
struct flock lock;
int fd, value;
if((fd = open(pidFile, O_WRONLY | O_CREAT,
(S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH))) < 0) {
condlog(0, "Cannot open pidfile [%s], error was [%s]",
pidFile, strerror(errno));
return -errno;
}
lock.l_type = F_WRLCK;
lock.l_start = 0;
lock.l_whence = SEEK_SET;
lock.l_len = 0;
if (fcntl(fd, F_SETLK, &lock) < 0) {
if (errno != EACCES && errno != EAGAIN)
condlog(0, "Cannot lock pidfile [%s], error was [%s]",
pidFile, strerror(errno));
else
condlog(0, "process is already running");
goto fail;
}
if (ftruncate(fd, 0) < 0) {
condlog(0, "Cannot truncate pidfile [%s], error was [%s]",
pidFile, strerror(errno));
goto fail;
}
memset(buf, 0, sizeof(buf));
snprintf(buf, sizeof(buf)-1, "%u", pid);
if (write(fd, buf, strlen(buf)) != (ssize_t)strlen(buf)) {
condlog(0, "Cannot write pid to pidfile [%s], error was [%s]",
pidFile, strerror(errno));
goto fail;
}
if ((value = fcntl(fd, F_GETFD, 0)) < 0) {
condlog(0, "Cannot get close-on-exec flag from pidfile [%s], "
"error was [%s]", pidFile, strerror(errno));
goto fail;
}
value |= FD_CLOEXEC;
if (fcntl(fd, F_SETFD, value) < 0) {
condlog(0, "Cannot set close-on-exec flag from pidfile [%s], "
"error was [%s]", pidFile, strerror(errno));
goto fail;
}
return fd;
fail:
close(fd);
return -errno;
}