From 2792e00e87c89cc11d9214733d6d52b127d15a07 Mon Sep 17 00:00:00 2001 From: Teodor Sigaev Date: Wed, 13 Apr 2016 23:00:35 +0300 Subject: [PATCH] improve log --- Makefile | 8 ++- main.c | 47 ++++++++-------- rc.d/trinketd | 2 +- tlog.c | 144 ++++++++++++++++++++++++++++++++++++++++++++++++++ tlog.h | 58 ++++++++++++++++++++ trinket.c | 49 +++++++++-------- 6 files changed, 255 insertions(+), 53 deletions(-) create mode 100644 tlog.c create mode 100644 tlog.h diff --git a/Makefile b/Makefile index 0c9fcc1..78e3db9 100644 --- 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 --- a/main.c +++ b/main.c @@ -26,6 +26,7 @@ *------------------------------------------------------------------------- */ +#include #include #include #include @@ -35,13 +36,13 @@ #include #include +#include #include 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 "); - 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); diff --git a/rc.d/trinketd b/rc.d/trinketd index 9e92010..de36188 100755 --- a/rc.d/trinketd +++ b/rc.d/trinketd @@ -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 index 0000000..8ec0abb --- /dev/null +++ b/tlog.c @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2004 Teodor Sigaev + * 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 +#include +#include +#include +#include +#include +#include +#include + +#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 index 0000000..62cbb82 --- /dev/null +++ b/tlog.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2004 Teodor Sigaev + * 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 +#include +#include + +#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 diff --git a/trinket.c b/trinket.c index 8f2cdc9..fa6598d 100644 --- a/trinket.c +++ b/trinket.c @@ -26,10 +26,11 @@ *------------------------------------------------------------------------- */ -#include #include #include #include + +#include #include #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; } -- 2.46.1