- import libpidfile for easier pidfile management instead of FreeBSD specific libutil

This commit is contained in:
Babak Farrokhi 2015-10-20 17:03:29 +03:30
parent 0bf9feeaf7
commit 6d3fb07414
4 changed files with 337 additions and 9 deletions

View File

@ -1,14 +1,24 @@
PREFIX=/usr/local
INC=-I$(PREFIX)/include
LIB=-L$(PREFIX)/lib -lutil
FLAGS=-Wall -O2 -pipe -funroll-loops -ffast-math -fno-strict-aliasing
LIB=-L$(PREFIX)/lib -L. -lpidfile
CFLAGS=-Wall -g -O2 -pipe -funroll-loops -ffast-math -fno-strict-aliasing
CC?=cc
AR?=AR
RANLIB?=ranlib
all: fsipd
PROGS = fsipd
LIBPIDFILE = libpidfile.a
OBJS = pidfile.o
fsipd: fsipd.c Makefile
$(CC) $(FLAGS) $(INC) $(LIB) fsipd.c -o fsipd
all: $(LIBPIDFILE) $(PROGS)
$(LIBPIDFILE) : $(OBJS)
$(AR) rv $(LIBPIDFILE) $?
$(RANLIB) $(LIBPIDFILE)
fsipd: fsipd.c $(LIBPIDFILE)
$(CC) $(CFLAGS) $(INC) $(LIB) fsipd.c -o fsipd
clean:
rm -f fsipd
rm -f *.o a.out core temp.* $(LIBPIDFILE) $(PROGS)
rm -fr *.dSYM

View File

@ -45,7 +45,7 @@
#include <sysexits.h>
#include <unistd.h>
#include <syslog.h>
#include <libutil.h>
#include "pidfile.h"
#define PORT 5060
#define BACKLOG 1024
@ -88,6 +88,7 @@ void
process_request(char *str)
{
/* check input str for SIP requests */
/*
* TODO: log connection info including SRC/DST IP, SRC/DST PORT,
* Timestamp and Message Type in CSV Format
@ -118,7 +119,7 @@ daemon_start()
if (errno == EEXIST) {
errx(EXIT_FAILURE, "Daemon already running, pid: %jd.", (intmax_t)otherpid);
}
warn("Cannot open or create pidfile.");
err(EXIT_FAILURE,"Cannot open or create pidfile");
}
/* setup socket */
if ((proto_tcp = getprotobyname("tcp")) == NULL)

286
pidfile.c Normal file
View File

@ -0,0 +1,286 @@
#include "pidfile.h"
struct pidfh {
int pf_fd;
char pf_path[MAXPATHLEN + 1];
dev_t pf_dev;
ino_t pf_ino;
};
static int _pidfile_remove(struct pidfh *pfh, int freeit);
static int
pidfile_verify(const struct pidfh *pfh)
{
struct stat sb;
if (pfh == NULL || pfh->pf_fd == -1)
return (EINVAL);
/*
* Check remembered descriptor.
*/
if (fstat(pfh->pf_fd, &sb) == -1)
return (errno);
if (sb.st_dev != pfh->pf_dev || sb.st_ino != pfh->pf_ino)
return (EINVAL);
return (0);
}
int
flopen(const char *path, int flags, ...)
{
int fd, operation, serrno, trunc;
struct stat sb, fsb;
int mode;
#ifdef O_EXLOCK
flags &= ~O_EXLOCK;
#endif
mode = 0;
if (flags & O_CREAT) {
va_list ap;
va_start(ap, flags);
mode = (int)va_arg(ap, int);
va_end(ap);
}
operation = LOCK_EX;
if (flags & O_NONBLOCK)
operation |= LOCK_NB;
trunc = (flags & O_TRUNC);
flags &= ~O_TRUNC;
for (;;) {
if ((fd = open(path, flags, mode)) == -1)
/* non-existent or no access */
return (-1);
if (flock(fd, operation) == -1) {
/* unsupported or interrupted */
serrno = errno;
(void)close(fd);
errno = serrno;
return (-1);
}
if (stat(path, &sb) == -1) {
/* disappeared from under our feet */
(void)close(fd);
continue;
}
if (fstat(fd, &fsb) == -1) {
/* can't happen [tm] */
serrno = errno;
(void)close(fd);
errno = serrno;
return (-1);
}
if (sb.st_dev != fsb.st_dev ||
sb.st_ino != fsb.st_ino) {
/* changed under our feet */
(void)close(fd);
continue;
}
if (trunc && ftruncate(fd, 0) != 0) {
/* can't happen [tm] */
serrno = errno;
(void)close(fd);
errno = serrno;
return (-1);
}
return (fd);
}
}
static int
pidfile_read(const char *path, pid_t *pidptr)
{
char buf[16], *endptr;
int error, fd, i;
fd = open(path, O_RDONLY | O_CLOEXEC);
if (fd == -1)
return (errno);
i = read(fd, buf, sizeof(buf) - 1);
error = errno; /* Remember errno in case close() wants to change it. */
close(fd);
if (i == -1)
return (error);
else if (i == 0)
return (EAGAIN);
buf[i] = '\0';
*pidptr = strtol(buf, &endptr, 10);
if (endptr != &buf[i])
return (EINVAL);
return (0);
}
struct pidfh *pidfile_open(const char *path, mode_t mode, pid_t *pidptr)
{
struct pidfh *pfh;
struct timespec rqtp;
struct stat sb;
int len, fd, error, count;
pfh = malloc(sizeof(*pfh));
if (pfh == NULL) return NULL;
if (path == NULL)
len = snprintf(pfh->pf_path, sizeof(pfh->pf_path), "/var/run/%s.pid", getprogname());
else
len = snprintf(pfh->pf_path, sizeof(pfh->pf_path), "%s", path);
if (len >= sizeof(pfh->pf_path)) {
free(pfh);
errno = ENAMETOOLONG;
return(NULL);
}
fd = flopen(pfh->pf_path, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NONBLOCK, mode);
if (fd == -1) {
if (errno == EWOULDBLOCK) {
if (pidptr == NULL) {
errno = EEXIST;
} else {
count = 20;
rqtp.tv_sec = 0;
rqtp.tv_nsec = 5000000;
for (;;) {
errno = pidfile_read(pfh->pf_path,pidptr);
if (errno != EAGAIN || --count == 0) break;
nanosleep(&rqtp, 0);
}
if (errno == EAGAIN) *pidptr = -1;
if (errno == 0 || errno == EAGAIN) errno = EEXIST;
}
}
free(pfh);
return(NULL);
}
if (fstat(fd, &sb) == -1) {
error = errno;
unlink(pfh->pf_path);
close(fd);
free(pfh);
errno = error;
return(NULL);
}
pfh->pf_fd = fd;
pfh->pf_dev = sb.st_dev;
pfh->pf_ino = sb.st_ino;
return(pfh);
}
static int
_pidfile_remove(struct pidfh *pfh, int freeit)
{
int error;
error = pidfile_verify(pfh);
if (error != 0) {
errno = error;
return (-1);
}
if (unlink(pfh->pf_path) == -1)
error = errno;
if (close(pfh->pf_fd) == -1) {
if (error == 0)
error = errno;
}
if (freeit)
free(pfh);
else
pfh->pf_fd = -1;
if (error != 0) {
errno = error;
return (-1);
}
return (0);
}
int
pidfile_remove(struct pidfh *pfh)
{
return (_pidfile_remove(pfh, 1));
}
int
pidfile_write(struct pidfh *pfh)
{
char pidstr[16];
int error, fd;
/*
* Check remembered descriptor, so we don't overwrite some other
* file if pidfile was closed and descriptor reused.
*/
errno = pidfile_verify(pfh);
if (errno != 0) {
/*
* Don't close descriptor, because we are not sure if it's ours.
*/
return (-1);
}
fd = pfh->pf_fd;
/*
* Truncate PID file, so multiple calls of pidfile_write() are allowed.
*/
if (ftruncate(fd, 0) == -1) {
error = errno;
_pidfile_remove(pfh, 0);
errno = error;
return (-1);
}
snprintf(pidstr, sizeof(pidstr), "%u", getpid());
if (pwrite(fd, pidstr, strlen(pidstr), 0) != (ssize_t)strlen(pidstr)) {
error = errno;
_pidfile_remove(pfh, 0);
errno = error;
return (-1);
}
return (0);
}
int
pidfile_close(struct pidfh *pfh)
{
int error;
error = pidfile_verify(pfh);
if (error != 0) {
errno = error;
return (-1);
}
if (close(pfh->pf_fd) == -1)
error = errno;
free(pfh);
if (error != 0) {
errno = error;
return (-1);
}
return (0);
}
int
pidfile_fileno(const struct pidfh *pfh)
{
if (pfh == NULL || pfh->pf_fd == -1) {
errno = EINVAL;
return (-1);
}
return (pfh->pf_fd);
}

31
pidfile.h Normal file
View File

@ -0,0 +1,31 @@
#ifndef _PIDFILE_H
#define _PIDFILE_H
#include <sys/file.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdarg.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <fcntl.h>
#include <time.h>
#include <string.h>
struct pidfh;
int flopen(const char *_path, int _flags, ...);
struct pidfh *pidfile_open(const char *path, mode_t mode, pid_t *pidptr);
int pidfile_write(struct pidfh *pfh);
int pidfile_close(struct pidfh *pfh);
int pidfile_remove(struct pidfh *pfh);
int pidfile_fileno(const struct pidfh *pfh);
#endif /* _PIDFILE_H */