From 6d3fb07414489f877adfb98bbf4aa6d86a6f72ad Mon Sep 17 00:00:00 2001 From: Babak Farrokhi Date: Tue, 20 Oct 2015 17:03:29 +0330 Subject: [PATCH] - import libpidfile for easier pidfile management instead of FreeBSD specific libutil --- Makefile | 24 +++-- fsipd.c | 5 +- pidfile.c | 286 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ pidfile.h | 31 ++++++ 4 files changed, 337 insertions(+), 9 deletions(-) create mode 100644 pidfile.c create mode 100644 pidfile.h diff --git a/Makefile b/Makefile index b5e8132..2f08a51 100644 --- a/Makefile +++ b/Makefile @@ -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 \ No newline at end of file diff --git a/fsipd.c b/fsipd.c index c5ed06e..d4fca6d 100644 --- a/fsipd.c +++ b/fsipd.c @@ -45,7 +45,7 @@ #include #include #include -#include +#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) diff --git a/pidfile.c b/pidfile.c new file mode 100644 index 0000000..48d3271 --- /dev/null +++ b/pidfile.c @@ -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); +} diff --git a/pidfile.h b/pidfile.h new file mode 100644 index 0000000..11b3775 --- /dev/null +++ b/pidfile.h @@ -0,0 +1,31 @@ +#ifndef _PIDFILE_H +#define _PIDFILE_H + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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 */ \ No newline at end of file