From 58bd6213ebd4d3ccb6d59d5dfaa1c9c6cb4ea0a1 Mon Sep 17 00:00:00 2001 From: Babak Farrokhi Date: Wed, 21 Oct 2015 17:13:44 +0330 Subject: [PATCH] - add logfile library for easier logging --- Makefile | 14 +++-- fsipd.c | 8 ++- logfile.c | 135 +++++++++++++++++++++++++++++++++++++++++++++++++ logfile.h | 62 +++++++++++++++++++++++ logfile_test.c | 62 +++++++++++++++++++++++ 5 files changed, 274 insertions(+), 7 deletions(-) create mode 100644 logfile.c create mode 100644 logfile.h create mode 100644 logfile_test.c diff --git a/Makefile b/Makefile index ef59260..7d3b7f9 100644 --- a/Makefile +++ b/Makefile @@ -4,13 +4,17 @@ LIB=-L$(PREFIX)/lib -lpidutil CFLAGS=-Wall -Wextra -g -O2 -pipe -funroll-loops -ffast-math -fno-strict-aliasing CC?=cc -PROGS = fsipd +PROGS = fsipd logfile_test +CFILES = fsipd.c logfile.c -all: $(PROGS) +all: fsipd -fsipd: fsipd.c - $(CC) $(CFLAGS) $(INC) $(LIB) fsipd.c -o fsipd +fsipd: $(CFILES) + $(CC) $(CFLAGS) $(INC) $(LIB) $(CFILES) -o fsipd + +test: logfile.c logfile_test.c + $(CC) $(CFLAGS) $(INC) $(LIB) logfile.c logfile_test.c -o logfile_test clean: - rm -f *.o *.a a.out core temp.* $(LIBPIDFILE) $(PROGS) + rm -f *.BAK *.log *.o *.a a.out core temp.* $(LIBPIDFILE) $(PROGS) rm -fr *.dSYM diff --git a/fsipd.c b/fsipd.c index b970385..5add59c 100644 --- a/fsipd.c +++ b/fsipd.c @@ -48,6 +48,8 @@ #include #include +#include "logfile.h" + #define PORT 5060 #define BACKLOG 1024 @@ -55,6 +57,7 @@ struct pidfh *pfh; struct sockaddr_in sa; struct protoent *proto_tcp, *proto_udp; +log_t *lh; /* * Prepare for a clean shutdown @@ -74,6 +77,7 @@ signal_handler(int sig) switch (sig) { case SIGHUP: + log_reopen(&lh); break; case SIGINT: case SIGTERM: @@ -91,7 +95,7 @@ process_request(char *str) /* check input str for SIP requests */ syslog(LOG_ALERT, "sip: %s, sport: %d, payload: \"%s\"\n", - inet_ntoa(sa.sin_addr), ntohs(sa.sin_port), str); + inet_ntoa(sa.sin_addr), ntohs(sa.sin_port), str); } /* @@ -116,7 +120,7 @@ daemon_start() if (errno == EEXIST) { errx(EXIT_FAILURE, "Daemon already running, pid: %jd.", (intmax_t)otherpid); } - err(EXIT_FAILURE,"Cannot open or create pidfile"); + err(EXIT_FAILURE, "Cannot open or create pidfile"); } /* setup socket */ if ((proto_tcp = getprotobyname("tcp")) == NULL) diff --git a/logfile.c b/logfile.c new file mode 100644 index 0000000..02bdf8e --- /dev/null +++ b/logfile.c @@ -0,0 +1,135 @@ +/*- + * Copyright (c) 2015, Babak Farrokhi + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "logfile.h" + +log_t * +log_open(const char *path, mode_t mode) +{ + log_t *lh; + struct stat sb; + char *filename; + int fd; + + if (path == NULL) { + asprintf(&filename, "%s/%s.log", LOGPATH, getprogname()); + } else { + filename = (char *)path; + } + + /* + * try to create / append the file and make sure it is correctly + * created + */ + if ((fd = open(filename, O_WRONLY | O_APPEND | O_CREAT | O_EXLOCK | O_SYNC, mode)) == -1) + return (NULL); + if (stat(filename, &sb) == -1) { + close(fd); + return (NULL); + } + /* initialize data structure */ + lh = calloc(1, sizeof(log_t)); + + lh->fd = fd; + lh->dev = sb.st_dev; + lh->ino = sb.st_ino; + lh->mode = sb.st_mode; + strncpy(lh->path, filename, strnlen(filename, MAXPATHLEN + 1)); + + return (lh); +} + +void +log_close(const log_t *log) +{ + if (!log_isopen(log)) + return; + + close(log->fd); + free((void *)log); +} + +inline bool +log_isopen(const log_t *log) +{ + if (log == NULL) + return (false); + return (log->fd != -1); +} + +void +log_reopen(log_t **log) +{ + log_t *newlog; + + if (!log_isopen(*log)) + return; + + newlog = malloc(sizeof(log_t)); + memcpy(newlog, *log, sizeof(log_t)); + log_close(*log); + *log = log_open(newlog->path, newlog->mode); + free(newlog); +} + +void +log_printf(const log_t *log, const char *format,...) +{ + va_list args; + char *message; + + /* + * todo: add timestamp and \n example: "Oct 21 13:46:35 %s\n" + */ + + if (log_isopen(log)) { + + va_start(args, format); + vasprintf(&message, format, args); + va_end(args); + + write(log->fd, message, strnlen(message, MAX_MSG_SIZE)); + } +} + +bool +log_verify(const log_t *log) +{ + struct stat sb; + + if (log == NULL || log->fd == -1) { + errno = EINVAL; + return (false); + } + if (fstat(log->fd, &sb) == -1) + return (false); + + if (log->ino != sb.st_ino || log->dev != sb.st_dev || log->mode != sb.st_mode) { + errno = EINVAL; + return (false); + } + return true; +} diff --git a/logfile.h b/logfile.h new file mode 100644 index 0000000..b867fcd --- /dev/null +++ b/logfile.h @@ -0,0 +1,62 @@ +/*- + * Copyright (c) 2015, Babak Farrokhi + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _LOGFILE_H +#define _LOGFILE_H + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#define LOGPATH "/var/log" +#define MAX_MSG_SIZE 65536 + +typedef struct _log_t { + int fd; + char path[MAXPATHLEN + 1]; + dev_t dev; + ino_t ino; + mode_t mode; +} log_t; + +log_t *log_open(const char *path, mode_t mode); +void log_close(const log_t *log); +bool log_isopen(const log_t *log); +bool log_verify(const log_t *log); +void log_reopen(log_t **log); +void log_printf(const log_t *log, const char *format,...); + +#endif /* _LOGFILE_H */ diff --git a/logfile_test.c b/logfile_test.c new file mode 100644 index 0000000..a70ff96 --- /dev/null +++ b/logfile_test.c @@ -0,0 +1,62 @@ +/*- + * Copyright (c) 2015, Babak Farrokhi + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include +#include +#include +#include +#include "logfile.h" + +/* + * dummy program to test logfile functionality + */ + +int +main(void) +{ + log_t *lh; + + if ((lh = log_open("test.log", 0600)) == NULL) { + err(EX_IOERR, "Cannot open log file"); + } + + if (!log_verify(lh)) + err(errno, "Failed to verify integrity of log file"); + + log_printf(lh, "opened file handle: %d , inode: %llu\n", lh->fd, lh->ino); + printf("logfile: %s, handle: %d, inode: %llu, mode: %d\n", lh->path, lh->fd, lh->ino, lh->mode); + + log_reopen(&lh); + if (!log_verify(lh)) + err(errno, "Failed to verify integrity of reopened log file"); + + log_printf(lh, "reopened file handle: %d , inode: %llu\n", lh->fd, lh->ino); + printf("logfile: %s, handle: %d, inode: %llu, mode: %d\n", lh->path, lh->fd, lh->ino, lh->mode); + + log_close(lh); + + return 0; +}