improve log
authorTeodor Sigaev <teodor@sigaev.ru>
Wed, 13 Apr 2016 20:00:35 +0000 (23:00 +0300)
committerTeodor Sigaev <teodor@sigaev.ru>
Wed, 13 Apr 2016 20:00:35 +0000 (23:00 +0300)
Makefile
main.c
rc.d/trinketd
tlog.c [new file with mode: 0644]
tlog.h [new file with mode: 0644]
trinket.c

index 0c9fcc1..78e3db9 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,11 +1,12 @@
 CC=cc
 INCLUDE=-I/usr/local/include -I.
 LIB=-L/usr/local/lib -lhidapi
+INSTALL=install -o root 
 ifndef OS
 OS=$(shell uname)
 endif
 
-CFLAGS=-Wall -pedantic -std=c99 -O2 -g
+CFLAGS=-Wall -pedantic -std=c99 -O2 -g -DASSERT_CORE
 ifeq ($(OS), FreeBSD)
 endif
 
@@ -13,7 +14,7 @@ ifeq ($(OS), Linux)
 CFLAGS+= -D_GNU_SOURCE -D_LARGE_FILES -D_FILE_OFFSET_BITS=64
 endif
 
-OBJ=trinket.o main.o
+OBJ=trinket.o main.o tlog.o
 
 .SUFFIXES: .o.c
 
@@ -28,3 +29,6 @@ trinketd: $(OBJ)
 clean:
        rm -rf *core *.o trinketd
 
+install: all
+       $(INSTALL) trinketd /usr/local/sbin/trinketd
+       $(INSTALL) rc.d/trinketd /usr/local/etc/rc.d/trinketd 
diff --git a/main.c b/main.c
index ff77ec5..6bbd6cf 100644 (file)
--- a/main.c
+++ b/main.c
@@ -26,6 +26,7 @@
  *-------------------------------------------------------------------------
  */
 
+#include <errno.h>
 #include <fcntl.h>
 #include <stdbool.h>
 #include <stdio.h>
 #include <hidapi/hidapi.h>
 #include <sys/param.h>
 
+#include <tlog.h>
 #include <trinket.h>
 
 static char*   dbdir = NULL;
 static int             period = 300; /* in seconds */
 static int             tics = 1;
 static char*   pidfile = NULL;
-static char*   logfile = NULL;
 static bool            daemonize = false;
 static char            tfile[MAXPATHLEN],
                                ofile[MAXPATHLEN];
@@ -52,7 +53,7 @@ static void
 usage(const char *errmsg) {
        puts("trinketd - collecting info from AtomPro");
        puts("Copyright (c) 2016, Teodor Sigaev <teodor@sigaev.ru>");
-       puts("trinketd [-d] [-l logfile] [-p pidfile] [-P period] [-D datadir] [-i tics]");
+       puts("trinketd [-d] [-p pidfile] [-P period] [-D datadir] [-i tics]");
 
        if (errmsg) {
                puts("");
@@ -71,20 +72,20 @@ main_loop() {
 
        prevDose = malloc(sizeof(*prevDose) * (tics + 1));
        if (!prevDose) {
-               fprintf(stderr, "could not allocate array, exiting...\n");
+               tlog(TL_CRIT, "could not allocate array, exiting...");
                return;
        }
 
        while(42) {
 
                if (trinketOpen() != ERR_OK) {
-                       fprintf(stderr, "trinketOpen fails\n");
+                       tlog(TL_ALARM, "trinketOpen fails");
                        sleep(1);
                        continue;
                }
 
                if (trinketGetCumDose(&curDose) != ERR_OK) {
-                       fprintf(stderr, "trinketGetCumDose fails\n");
+                       tlog(TL_ALARM, "trinketGetCumDose fails");
                        trinketClose();
                        sleep(1);
                        continue;
@@ -109,7 +110,7 @@ main_loop() {
 
                        if (daemonize) {
                                if ((fh = fopen(tfile, "w")) == NULL) {
-                                       fprintf(stderr, "fopen fails\n");
+                                       tlog(TL_ALARM, "fopen fails: %s", strerror(errno));
                                        successOpen = false;
                                }
                        }
@@ -138,9 +139,9 @@ extern int opterr, optind;
 
 int
 main(int argn, char* argv[]) {
-       int i;
-       int     pidfd,
-               logfd;
+       int             i;
+       int             pidfd;
+       char    *logfile = NULL;
 
        opterr = 0;
        while((i=getopt(argn,argv,"dD:i:l:p:P:h")) != EOF) {
@@ -190,35 +191,31 @@ main(int argn, char* argv[]) {
                        usage("could not write pidfile");
        }
 
-       if (logfile) {
-               logfd = open(logfile, O_CREAT | O_WRONLY | O_APPEND, 0666);
-               if (logfd < 0)
-                       usage("could not write logfile");
-       }
-
        if (daemonize) {
+               opentlog((logfile == NULL) ? TL_OPEN_SYSLOG : TL_OPEN_FILE,
+                                TL_INFO, logfile);
+
                if (daemon(0, 0) == -1)
-                       usage("could not daemonize");
+                       tlog(TL_CRIT | TL_EXIT, "could not daemonize");
+       } else {
+               opentlog(TL_OPEN_STDERR | TL_OPEN_FILE, TL_INFO, logfile);
        }
 
+
+
        if (pidfile) {
                char pid[64];
 
                snprintf(pid, sizeof(pid), "%lld", (long long)getpid());
                if (write(pidfd, pid, strlen(pid)) != strlen(pid))
-                       usage("could not write pid");
+                       tlog(TL_CRIT | TL_EXIT, "could not write pid");
                close(pidfd);
        }
 
-       if (logfile) {
-               dup2(logfd, fileno(stderr));
-               close(logfd);
-       }
+       tlog(TL_CRIT, "trinketd started, pid: %lld", (long long)getpid());
 
-       if (hid_init() < 0) {
-               fprintf(stderr, "hid_init fails\n");
-               exit(1);
-       }
+       if (hid_init() < 0)
+               tlog(TL_CRIT | TL_EXIT, "hid_init fails");
 
        if (dbdir) {
                snprintf(tfile, MAXPATHLEN, "%s/trinket.tmp", dbdir);
index 9e92010..de36188 100755 (executable)
@@ -15,8 +15,8 @@
 name=trinketd
 rcvar=trinketd_enable
 
-logfile="/var/log/${name}.log"
 pidfile="/var/run/${name}.pid"
+logfile="/var/log/${name}.log"
 dbdir="/var/db/trinket"
 procname="/usr/local/sbin/trinketd"
 
diff --git a/tlog.c b/tlog.c
new file mode 100644 (file)
index 0000000..8ec0abb
--- /dev/null
+++ b/tlog.c
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2004 Teodor Sigaev <teodor@sigaev.ru>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *        notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ *        may be used to endorse or promote products derived from this software
+ *        without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY 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 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 <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <syslog.h>
+#include <stdarg.h>
+
+#include "tlog.h"
+
+static FILE                    *TL_ErrOut = NULL;
+static u_int32_t       TL_DebugLevel = TL_INFO;
+static u_int32_t       tlflag = TL_OPEN_STDERR | TL_OPEN_SYSLOG;
+
+
+static int
+TLtoSYS(int level) {
+       level &= ~TL_EXIT;
+       switch(level) {
+               case    TL_CRIT : return LOG_CRIT;
+               case    TL_ALARM: return LOG_ERR;
+               case    TL_WARN : return LOG_WARNING;
+               case    TL_INFO : return LOG_INFO;
+               case    TL_DEBUG: return LOG_DEBUG;
+               default: return LOG_WARNING;
+       }
+       return LOG_ERR;
+}
+
+void
+opentlog(u_int32_t flag, u_int32_t level, char *file) {
+       if (flag==0)
+               flag=tlflag;
+
+       TL_DebugLevel=level;
+
+       tlflag &= ~TL_OPEN_FILE;
+       if ( TL_ErrOut )
+               fclose(TL_ErrOut);
+       if ( (flag & TL_OPEN_FILE) && file ) {
+               if ( (TL_ErrOut=fopen(file,"a")) == NULL )
+                       tlog(TL_ALARM,"Can't open log file '%s': %s", file, strerror(errno));
+               else {
+                       u_int32_t oldflag = tlflag;
+                       tlflag = TL_OPEN_FILE;
+                       tlog(TL_INFO, "Log opened");
+                       tlflag = oldflag | TL_OPEN_FILE;
+               }
+       }
+
+       tlflag &= ~TL_OPEN_SYSLOG;
+       tlflag |= (flag & TL_OPEN_SYSLOG);
+
+       tlflag &= ~TL_OPEN_STDERR;
+       tlflag |= (flag & TL_OPEN_STDERR);
+}
+
+void
+closetlog() {
+       if ( TL_ErrOut ) {
+               if ( tlflag & TL_OPEN_FILE ) {
+                       tlflag = TL_OPEN_FILE;
+                       tlog(TL_INFO,"Log closed");
+               }
+               fclose(TL_ErrOut);
+       }
+       TL_ErrOut=NULL;
+       tlflag = TL_OPEN_STDERR | TL_OPEN_SYSLOG;
+}
+
+void
+tlog(u_int32_t level,const char *format, ...) {
+       va_list args;
+
+       if ( (level & TL_EXIT)==0 )
+               if ( (level & ~TL_EXIT) > TL_DebugLevel )
+                       return;
+
+       if ( tlflag & (TL_OPEN_STDERR | TL_OPEN_FILE) ) {
+               time_t t;
+               char buf[64];
+               t = time(NULL);
+
+               strftime(buf,64,"%H:%M:%S %d/%m/%Y",localtime(&t));
+               if ( tlflag & TL_OPEN_STDERR ) {
+                       fprintf( stderr,"%d %s ", getpid(), buf );
+                       va_start(args, format);
+                       vfprintf( stderr, format, args);
+                       va_end(args);
+                       fputc('\n', stderr);
+               }
+               if ( (tlflag & TL_OPEN_FILE) && TL_ErrOut ) {
+                       fprintf( TL_ErrOut,"%d %s ", getpid(), buf );
+                       va_start(args, format);
+                       vfprintf( TL_ErrOut, format, args);
+                       va_end(args);
+                       fputc('\n', TL_ErrOut);
+                       fflush(TL_ErrOut);
+               }
+       }
+
+       if ( tlflag & TL_OPEN_SYSLOG ) {
+               va_start(args, format);
+               vsyslog( TLtoSYS(level),  format, args );
+               va_end(args);
+       }
+
+       if ( level & TL_EXIT ) {
+               tlog(level & ~TL_EXIT, "Exitting...");
+               closetlog();
+               exit(1);
+       }
+}
+
diff --git a/tlog.h b/tlog.h
new file mode 100644 (file)
index 0000000..62cbb82
--- /dev/null
+++ b/tlog.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2004 Teodor Sigaev <teodor@sigaev.ru>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *        notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ *        may be used to endorse or promote products derived from this software
+ *        without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY 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 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 __TLOG_H__
+#define __TLOG_H__
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+
+#define TL_EXIT                0x70000000
+#define TL_CRIT                0
+#define TL_ALARM       1
+#define TL_WARN                2
+#define TL_INFO                3
+#define TL_DEBUG       4
+
+#define TL_OPEN_SYSLOG         0x01
+#define TL_OPEN_STDERR         0x02
+#define TL_OPEN_FILE           0x04
+
+void opentlog(u_int32_t flag, u_int32_t level, char *file);
+void tlog(u_int32_t level,const char *format, ...);
+void closetlog();
+
+#ifdef ASSERT_CORE
+#define tassert(e)   ( (e) ? (void)0 : (tlog(TL_CRIT, "Assertion failed: %s, function %s, file %s, line %d.", #e, __func__, __FILE__, __LINE__), closetlog(), abort()) )
+#else
+#define tassert(e)   ( (e) ? (void)0 : (tlog(TL_CRIT|TL_EXIT, "Assertion failed: %s, function %s, file %s, line %d.", #e, __func__, __FILE__, __LINE__)) )
+#endif
+
+#endif
index 8f2cdc9..fa6598d 100644 (file)
--- a/trinket.c
+++ b/trinket.c
  *-------------------------------------------------------------------------
  */
 
-#include <assert.h>
 #include <stdint.h>
 #include <stdio.h>
 #include <hidapi/hidapi.h>
+
+#include <tlog.h>
 #include <trinket.h>
 
 #define         packed_struct __attribute__((packed))
@@ -106,17 +107,15 @@ dumpBuf(char *msg, uint8_t *buf, int len) {
 TrinketErrorCode
 trinketOpen() {
        TrinketErrorCode        r;
-#ifndef NDEBUG
        int i;
 
        for(i = 0; i < sizeof(protoDesc) / sizeof(*protoDesc); i++)
-               assert(i == protoDesc[i].cmdId);
-#endif
+               tassert(i == protoDesc[i].cmdId);
 
        trinketDev = hid_open(0x2047, 0x0301, NULL);
 
        if (trinketDev == NULL) {
-               fprintf(stderr, "hid_open fails\n");
+               tlog(TL_WARN, "hid_open fails");
                return ERR_ERROR;
        }
 
@@ -157,14 +156,14 @@ trinketPing() {
        } resp;
        int     r;
 
-       assert(proto->cmdId == CMD_PING);
-       assert(sizeof(cmd) == cmd.len + sizeof(ProtoHeader));
-       assert(sizeof(resp) == proto->respLen + sizeof(ProtoHeader));
+       tassert(proto->cmdId == CMD_PING);
+       tassert(sizeof(cmd) == cmd.len + sizeof(ProtoHeader));
+       tassert(sizeof(resp) == proto->respLen + sizeof(ProtoHeader));
 
        r = hid_write(trinketDev, (unsigned char*)&cmd, sizeof(cmd));
 
        if (r < 0 || r != sizeof(cmd)) {
-               fprintf(stderr, "hid_write  returns %d instead of %u\n", r, cmd.len);
+               tlog(TL_WARN, "hid_write  returns %d instead of %u", r, cmd.len);
                return ERR_ERROR;
        }
 
@@ -173,32 +172,32 @@ trinketPing() {
 
        r = hid_read_timeout(trinketDev, (unsigned char*)&resp, sizeof(resp), DEV_TIMEOUT);
        if (r < 0) {
-               fprintf(stderr, "hid_read_timeout fails\n");
+               tlog(TL_WARN, "hid_read_timeout fails");
                return  ERR_NO_ANSWER;
        }
 
        if (r != sizeof(resp)) {
-               fprintf(stderr, "hid_read_timeout  returns %d instead of %u\n", r, (unsigned int)sizeof(resp));
+               tlog(TL_WARN, "hid_read_timeout  returns %d instead of %u", r, (unsigned int)sizeof(resp));
                return ERR_ERROR;
        }
 
        if (resp.header.reportId != REPORT_ID) {
-               fprintf(stderr, "hid_read_timeout  returns report id %02x instead of %02x\n", resp.header.reportId, REPORT_ID);
+               tlog(TL_WARN, "hid_read_timeout  returns report id %02x instead of %02x", resp.header.reportId, REPORT_ID);
                return ERR_ERROR;
        }
 
        if (resp.header.size != proto->respLen) {
-               fprintf(stderr, "hid_read_timeout returns length %u intsead if %u\n", resp.header.size, proto->respLen);
+               tlog(TL_WARN, "hid_read_timeout returns length %u intsead if %u", resp.header.size, proto->respLen);
                return ERR_PROTO;
        }
 
        if (resp.len != proto->respLen) {
-               fprintf(stderr, "hid_read_timeout response length %u instead of %u\n", resp.len, proto->respLen);
+               tlog(TL_WARN, "hid_read_timeout response length %u instead of %u", resp.len, proto->respLen);
                return ERR_PROTO;
        }
 
        if (!(resp.begin == ACK_ANSWER_OK && resp.payload == 0 && resp.end == END_ANSWER)) {
-               fprintf(stderr, "hid_read_timeout  ACK %02x with payload %u and ETB %02x\n", resp.begin, resp.payload, resp.end);
+               tlog(TL_WARN, "hid_read_timeout  ACK %02x with payload %u and ETB %02x", resp.begin, resp.payload, resp.end);
                return ERR_PROTO;
        }
 
@@ -230,14 +229,14 @@ trinketGetCumDose(double *value) {
        } resp;
        int     r;
 
-       assert(proto->cmdId == CMD_CUM_DOSE);
-       assert(sizeof(cmd) == cmd.len + sizeof(ProtoHeader));
-       assert(sizeof(resp) == proto->respLen + sizeof(ProtoHeader));
+       tassert(proto->cmdId == CMD_CUM_DOSE);
+       tassert(sizeof(cmd) == cmd.len + sizeof(ProtoHeader));
+       tassert(sizeof(resp) == proto->respLen + sizeof(ProtoHeader));
 
        r = hid_write(trinketDev, (unsigned char*)&cmd, sizeof(cmd));
 
        if (r < 0 || r != sizeof(cmd)) {
-               fprintf(stderr, "hid_send_feature_report  returns %d instead of %u\n", r, cmd.len);
+               tlog(TL_WARN, "hid_send_feature_report  returns %d instead of %u", r, cmd.len);
                return ERR_ERROR;
        }
 
@@ -246,32 +245,32 @@ trinketGetCumDose(double *value) {
 
        r = hid_read_timeout(trinketDev, (unsigned char*)&resp, sizeof(resp), DEV_TIMEOUT);
        if (r < 0) {
-               fprintf(stderr, "hid_read_timeout fails\n");
+               tlog(TL_WARN, "hid_read_timeout fails");
                return  ERR_NO_ANSWER;
        }
 
        if (r != sizeof(resp)) {
-               fprintf(stderr, "hid_read_timeout  returns %d instead of %u\n", r, (unsigned int)sizeof(resp));
+               tlog(TL_WARN, "hid_read_timeout  returns %d instead of %u", r, (unsigned int)sizeof(resp));
                return ERR_ERROR;
        }
 
        if (resp.header.reportId != REPORT_ID) {
-               fprintf(stderr, "hid_read_timeout  returns report id %02x instead of %02x\n", resp.header.reportId, REPORT_ID);
+               tlog(TL_WARN, "hid_read_timeout  returns report id %02x instead of %02x", resp.header.reportId, REPORT_ID);
                return ERR_ERROR;
        }
 
        if (resp.header.size != proto->respLen) {
-               fprintf(stderr, "hid_read_timeout returns length %u intsead if %u\n", resp.header.size, proto->respLen);
+               tlog(TL_WARN, "hid_read_timeout returns length %u intsead if %u", resp.header.size, proto->respLen);
                return ERR_PROTO;
        }
 
        if (resp.len != proto->respLen) {
-               fprintf(stderr, "hid_read_timeout response length %u instead of %u\n", resp.len, proto->respLen);
+               tlog(TL_WARN, "hid_read_timeout response length %u instead of %u", resp.len, proto->respLen);
                return ERR_PROTO;
        }
 
        if (!(resp.begin == ACK_ANSWER_OK && resp.end == END_ANSWER)) {
-               fprintf(stderr, "hid_read_timeout  ACK %02x and ETB %02x\n", resp.begin, resp.end);
+               tlog(TL_WARN, "hid_read_timeout  ACK %02x and ETB %02x", resp.begin, resp.end);
                return ERR_PROTO;
        }