waveview/ttg/msglog.c

424 lines
8.7 KiB
C

/**
* \file msglog.c
* \brief Functions for printing messages, warnings and errors.
*
* This module provides output printing facilities.
*
* include LICENSE
*/
#define _GNU_SOURCE
#include <stdio.h>
#include <signal.h>
#include <stdarg.h>
#include <string.h>
#include <time.h>
#include <sys/types.h>
#include <unistd.h>
#include <errno.h>
#include <ctype.h>
#include <msglog.h>
#include <duprintf.h>
#ifdef TRACE_MEM
#include <tracemem.h>
#endif
#define MSG_FMT_DATE \
"%2d %3s %4d %2d:%02d:%02d", \
ptm->tm_mday, msg_month_of_year[ptm->tm_mon], (1900 + ptm->tm_year), \
ptm->tm_hour, ptm->tm_min, ptm->tm_sec
const char *msg_month_of_year[] = {
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
};
const char *msg_day_of_week[] = {
"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
};
const char *msg_typename[] = {
"DEBUG",
"INFO",
"WARNING",
"ERROR",
"FATAL",
};
/* see man console_codes */
#define COL(x) "\033[" #x ";1m"
#define RED COL(31)
#define GREEN COL(32)
#define YELLOW COL(33)
#define BLUE COL(34)
#define MAGENTA COL(35)
#define CYAN COL(36)
#define WHITE COL(37)
#define GRAY "\033[0m" /* end of color */
const char *msg_color[] = {
"", /* Debug */
"", /* info */
GREEN, /* Warning */
RED, /* Error */
BLUE, /* Fatal */
};
int prog_debug; /* global turn debug on */
MsgLogData *msglogp; /* global pointeur to MsgLogData in main */
/*
* struct _MsgLogData moved from msglog.h
* Let use different msglog.c without changing msglog.h
*/
struct _MsgLogData {
FILE *msg_fd;
FILE *dbg_fd; /* debug message file desc */
char *msg_progname;
int msg_flags;
int msg_verbose_level;
int msg_dbg_msk;
// int msg_dump_msk;
char *msg_filename;
int log_facility; /* storage for facility used in syslog */
int logger_is_open; /* set if openlog has been called */
MsgFunc msg_displayFunc;
};
/*
* if given filename store message in file
* if given displayFunc call func to display messge
* except for debug message
*/
void msg_set_func(MsgFunc displayFunc)
{
msglogp->msg_displayFunc = displayFunc;
if (displayFunc) {
msglogp->msg_flags &= ~MSG_F_TYPE;
}
}
void msg_set_facility(int facility)
{
msglogp->log_facility = facility;
}
int msg_get_facility(void)
{
return msglogp->log_facility;
}
void msg_set_logger_is_open(int is_open)
{
msglogp->logger_is_open = is_open;
}
int msg_get_logger_is_open(void)
{
return msglogp->logger_is_open;
}
void msg_initlog(char *name, int flags, char *filename,
MsgFunc displayFunc)
{
if (!msglogp) {
msglogp = app_new0(MsgLogData, 1);
}
msglogp->msg_progname = name;
msglogp->msg_flags = flags;
msglogp->msg_verbose_level = 1;
msglogp->msg_dbg_msk = 1;
msg_set_func(displayFunc);
msglogp->msg_fd = stderr;
msglogp->dbg_fd = stderr;
if (filename) {
char *omode = "a";
if (flags & MSG_F_OVERWRITE) {
omode = "w";
}
msg_openlog(filename, omode);
}
atexit(msg_closelog);
}
FILE * msg_get_msg_fd(void)
{
return msglogp->msg_fd;
}
void msg_set_dbg_fd(FILE * msg_fd )
{
msglogp->dbg_fd = msg_fd;
}
void msg_atexit(void)
{
if (msglogp) {
if (msglogp->msg_flags & MSG_F_SIGNAL) {
kill(getppid(), SIGQUIT);
}
msg_closelog();
app_free(msglogp);
msglogp = NULL;
}
}
void msg_set_flags(int flags)
{
msglogp->msg_flags = flags;
}
void msg_set_level(int level)
{
msglogp->msg_verbose_level = level;
}
int msg_get_level(void)
{
return msglogp->msg_verbose_level;
}
#ifdef MSG_DEBUG
void private_msg_set_dbg_msk(int msk)
{
msglogp->msg_dbg_msk = msk;
}
int private_msg_get_dbg_msk(void)
{
return msglogp->msg_dbg_msk;
}
void private_msg_get_dbg_msk_str(char *msg)
{
unsigned int i;
int k = 0;
int msk = msglogp->msg_dbg_msk;
for ( i = 0 ; i < 8 * sizeof(int) ; i++ ){
if ( msk & (1 << i) ){
if ( k ) {
msg[k] = ',';
k++;
}
sprintf(&msg[k], "%d", i);
k++;
if ( i > 9) {
k++;
}
}
}
msg[k] = 0;
}
unsigned int private_msg_set_dbg_msk_str(char *p)
{
unsigned int ui = 1;
int i;
if ( *p == 0 ){
prog_debug = 0;
goto finish;
}
while (1) {
i = strtoul(p, &p, 10);
ui |= (1 << i);
if (*p == 0) {
break;
}
p++;
}
prog_debug = 1;
finish:
msglogp->msg_dbg_msk = ui;
return ui;
}
#endif
#ifdef MSG_DUMP
void private_msg_dump(int level, char *buf, int len, int start, FILE *fd,
char *fmt, ...)
{
int i;
int n;
char msgbuf[50];
char lastline[50];
char cbuf[18];
int dup = 0;
int print_offset = 1;
va_list ap;
if ((level & msglogp->msg_dbg_msk) == 0) {
return;
}
if ( fd == NULL ){
fd = msglogp->msg_fd;
}
if (fmt) {
char *ffmt;
va_start(ap, fmt);
ffmt = app_strdup_vprintf(fmt, ap);
va_end(ap);
fprintf(fd, "%s: %d\n", ffmt, len );
app_free(ffmt);
}
if ( start == -1 ){
print_offset = 0;
}
lastline[0] = 0;
while (len > 0) {
int k = 0;
n = 16;
if (len < n) {
n = len;
}
for (i = 0; i < n; i++) {
sprintf(&msgbuf[k], "%02X ", (unsigned char) *buf);
k += 3;
if ( i == 7){
msgbuf[k] =' ';
k++;
}
if (isprint(*buf & 0x7F)) {
cbuf[i] = *buf & 0x7F;
} else {
cbuf[i] = '.';
}
buf++;
}
cbuf[i] = 0;
msgbuf[k] = 0;
len -= i;
if (strcmp(msgbuf, lastline) == 0 && len > 0) {
dup++;
} else {
if (dup > 0) {
fprintf(fd, " -- prev line repeats %d times --\n", dup);
}
dup = 0;
strcpy(lastline, msgbuf);
if ( print_offset ){
fprintf(fd, "%8X: ", (unsigned int) start);
}
fprintf(fd, "%-49s %s\n", msgbuf, cbuf);
}
start += n;
}
}
#endif
/*
* msg_openlog :
* send log messages to a file if needed
*/
FILE *msg_openlog(char *filename, char *mode)
{
msglogp->msg_filename = filename;
if ((msglogp->msg_fd = fopen(filename, mode)) == NULL) {
msglogp->msg_fd = stderr; /* just to get the next mesg */
msg_fatal(_("Can't open file '%s': %s"), filename, strerror(errno));
}
if ( prog_debug ){
msglogp->dbg_fd = msglogp->msg_fd;
}
return msglogp->msg_fd;
}
void msg_closelog(void)
{
if (msglogp->msg_fd != stderr) {
fclose(msglogp->msg_fd);
msglogp->msg_fd = stderr;
}
}
void msg_str_time_date(char *strdate);
void msg_str_time_date(char *strdate)
{
time_t now;
struct tm *ptm;
time(&now);
ptm = localtime(&now);
sprintf(strdate, MSG_FMT_DATE);
}
void private_message(int level, int msgtype, const char *func, char *file,
int line, char *fmt, ...)
{
va_list ap;
char *ffmt;
char date[128];
char text[128];
char *p;
char *color_s = "";
char *color_e = "";
if (msgtype == MSG_T_DEBUG) {
if ((msglogp->msg_dbg_msk & level) == 0) {
return;
}
} else if (level > msglogp->msg_verbose_level) {
return;
}
date[0] = 0;
if (msglogp->msg_flags & MSG_F_DATE) {
msg_str_time_date(date);
strcat(date, ": ");
}
if (msglogp->msg_flags & MSG_F_PROG) {
if (msglogp->msg_progname && *msglogp->msg_progname) {
p = date + strlen(date);
snprintf(p, sizeof(date) - strlen(date), "%s: ",
msglogp->msg_progname);
}
}
text[0] = 0;
if (msgtype == MSG_T_DEBUG || msglogp->msg_flags & MSG_F_TYPE) {
p = text + strlen(text);
snprintf(p, sizeof(text) - strlen(text), "%s: ",
msg_typename[msgtype]);
}
if (msglogp->msg_flags & MSG_F_FUNC) {
p = text + strlen(text);
snprintf(p, sizeof(text) - strlen(text), "%s: ", func);
}
if (msglogp->msg_flags & MSG_F_FILE) {
p = text + strlen(text);
snprintf(p, sizeof(text) - strlen(text), "%s:%d: ", file, line);
}
if (msglogp->msg_flags & MSG_F_COLOR) {
color_s = (char *) msg_color[msgtype];
if (msgtype > MSG_T_INFO) {
color_e = GRAY;
}
}
va_start(ap, fmt);
ffmt = app_strdup_vprintf(fmt, ap);
va_end(ap);
if (msglogp->msg_flags & MSG_F_FOLD) {
if (strlen(date) + strlen(text) + strlen(ffmt) > 80) {
strcat(text, "\n ");
}
}
if (msgtype == MSG_T_DEBUG) {
fprintf(msglogp->dbg_fd, "%s%s%s\n", date, text, ffmt);
fflush(msglogp->dbg_fd);
} else if (msglogp->msg_displayFunc) {
char message[1024];
snprintf(message, sizeof(message), "%s%s%s\n", date, text, ffmt);
(msglogp->msg_displayFunc) (msgtype, message);
} else {
fprintf(msglogp->msg_fd, "%s%s%s%s%s\n", color_s, date, text, ffmt,
color_e);
fflush(msglogp->msg_fd);
}
app_free(ffmt);
}