mosquitto/src/logging.c

275 lines
6.2 KiB
C
Raw Normal View History

2014-05-07 22:27:00 +00:00
/*
Copyright (c) 2009-2015 Roger Light <roger@atchoo.org>
2014-05-07 22:27:00 +00:00
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
and Eclipse Distribution License v1.0 which accompany this distribution.
The Eclipse Public License is available at
http://www.eclipse.org/legal/epl-v10.html
and the Eclipse Distribution License is available at
http://www.eclipse.org/org/documents/edl-v10.php.
Contributors:
Roger Light - initial implementation and documentation.
*/
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#ifndef WIN32
#include <syslog.h>
#endif
2014-06-02 00:01:29 +00:00
#include <time.h>
2014-05-07 22:27:00 +00:00
#ifndef CMAKE
#include <config.h>
#endif
#include <mosquitto_broker.h>
#include <memory_mosq.h>
2015-02-05 22:44:38 +00:00
#include <util_mosq.h>
2014-05-07 22:27:00 +00:00
extern struct mosquitto_db int_db;
#ifdef WIN32
HANDLE syslog_h;
#endif
/* Options for logging should be:
*
* A combination of:
* Via syslog
* To a file
* To stdout/stderr
* To topics
*/
/* Give option of logging timestamp.
* Logging pid.
*/
static int log_destinations = MQTT3_LOG_STDERR;
static int log_priorities = MOSQ_LOG_ERR | MOSQ_LOG_WARNING | MOSQ_LOG_NOTICE | MOSQ_LOG_INFO;
2015-02-05 22:44:38 +00:00
int mqtt3_log_init(struct mqtt3_config *config)
2014-05-07 22:27:00 +00:00
{
int rc = 0;
2015-02-05 22:44:38 +00:00
log_priorities = config->log_type;
log_destinations = config->log_dest;
2014-05-07 22:27:00 +00:00
if(log_destinations & MQTT3_LOG_SYSLOG){
#ifndef WIN32
2015-02-05 22:44:38 +00:00
openlog("mosquitto", LOG_PID|LOG_CONS, config->log_facility);
2014-05-07 22:27:00 +00:00
#else
syslog_h = OpenEventLog(NULL, "mosquitto");
#endif
}
2015-02-05 22:44:38 +00:00
if(log_destinations & MQTT3_LOG_FILE){
if(drop_privileges(config, true)){
return 1;
}
config->log_fptr = mosquitto__fopen(config->log_file, "at");
2015-02-05 22:44:38 +00:00
if(!config->log_fptr){
mosquitto__log_printf(NULL, MOSQ_LOG_ERR, "Error: Unable to open log file %s for writing.", config->log_file);
2015-02-05 22:44:38 +00:00
return MOSQ_ERR_INVAL;
}
restore_privileges();
2015-02-05 22:44:38 +00:00
}
2014-05-07 22:27:00 +00:00
return rc;
}
2015-02-05 22:44:38 +00:00
int mqtt3_log_close(struct mqtt3_config *config)
2014-05-07 22:27:00 +00:00
{
if(log_destinations & MQTT3_LOG_SYSLOG){
#ifndef WIN32
closelog();
#else
CloseEventLog(syslog_h);
#endif
}
2015-02-05 22:44:38 +00:00
if(log_destinations & MQTT3_LOG_FILE){
if(config->log_fptr){
fclose(config->log_fptr);
config->log_fptr = NULL;
2015-02-05 22:44:38 +00:00
}
}
2014-05-07 22:27:00 +00:00
2015-02-05 22:44:38 +00:00
/* FIXME - do something for all destinations! */
2014-05-07 22:27:00 +00:00
return MOSQ_ERR_SUCCESS;
}
int mosquitto__log_vprintf(struct mosquitto *mosq, int priority, const char *fmt, va_list va)
2014-05-07 22:27:00 +00:00
{
char *s;
char *st;
int len;
#ifdef WIN32
char *sp;
#endif
const char *topic;
int syslog_priority;
time_t now = time(NULL);
static time_t last_flush = 0;
2014-05-07 22:27:00 +00:00
if((log_priorities & priority) && log_destinations != MQTT3_LOG_NONE){
switch(priority){
case MOSQ_LOG_SUBSCRIBE:
topic = "$SYS/broker/log/M/subscribe";
#ifndef WIN32
syslog_priority = LOG_NOTICE;
#else
syslog_priority = EVENTLOG_INFORMATION_TYPE;
#endif
break;
case MOSQ_LOG_UNSUBSCRIBE:
topic = "$SYS/broker/log/M/unsubscribe";
#ifndef WIN32
syslog_priority = LOG_NOTICE;
#else
syslog_priority = EVENTLOG_INFORMATION_TYPE;
#endif
break;
case MOSQ_LOG_DEBUG:
topic = "$SYS/broker/log/D";
#ifndef WIN32
syslog_priority = LOG_DEBUG;
#else
syslog_priority = EVENTLOG_INFORMATION_TYPE;
#endif
break;
case MOSQ_LOG_ERR:
topic = "$SYS/broker/log/E";
#ifndef WIN32
syslog_priority = LOG_ERR;
#else
syslog_priority = EVENTLOG_ERROR_TYPE;
#endif
break;
case MOSQ_LOG_WARNING:
topic = "$SYS/broker/log/W";
#ifndef WIN32
syslog_priority = LOG_WARNING;
#else
syslog_priority = EVENTLOG_WARNING_TYPE;
#endif
break;
case MOSQ_LOG_NOTICE:
topic = "$SYS/broker/log/N";
#ifndef WIN32
syslog_priority = LOG_NOTICE;
#else
syslog_priority = EVENTLOG_INFORMATION_TYPE;
#endif
break;
case MOSQ_LOG_INFO:
topic = "$SYS/broker/log/I";
#ifndef WIN32
syslog_priority = LOG_INFO;
#else
syslog_priority = EVENTLOG_INFORMATION_TYPE;
#endif
break;
2015-02-13 22:57:49 +00:00
#ifdef WITH_WEBSOCKETS
case MOSQ_LOG_WEBSOCKETS:
topic = "$SYS/broker/log/WS";
#ifndef WIN32
syslog_priority = LOG_DEBUG;
#else
syslog_priority = EVENTLOG_INFORMATION_TYPE;
#endif
break;
#endif
2014-05-07 22:27:00 +00:00
default:
topic = "$SYS/broker/log/E";
#ifndef WIN32
syslog_priority = LOG_ERR;
#else
syslog_priority = EVENTLOG_ERROR_TYPE;
#endif
}
len = strlen(fmt) + 500;
s = mosquitto__malloc(len*sizeof(char));
2014-05-07 22:27:00 +00:00
if(!s) return MOSQ_ERR_NOMEM;
vsnprintf(s, len, fmt, va);
s[len-1] = '\0'; /* Ensure string is null terminated. */
if(log_destinations & MQTT3_LOG_STDOUT){
if(int_db.config && int_db.config->log_timestamp){
fprintf(stdout, "%d: %s\n", (int)now, s);
}else{
fprintf(stdout, "%s\n", s);
}
fflush(stdout);
}
if(log_destinations & MQTT3_LOG_STDERR){
if(int_db.config && int_db.config->log_timestamp){
fprintf(stderr, "%d: %s\n", (int)now, s);
}else{
fprintf(stderr, "%s\n", s);
}
fflush(stderr);
}
if(log_destinations & MQTT3_LOG_FILE && int_db.config->log_fptr){
if(int_db.config && int_db.config->log_timestamp){
fprintf(int_db.config->log_fptr, "%d: %s\n", (int)now, s);
}else{
fprintf(int_db.config->log_fptr, "%s\n", s);
}
if(now - last_flush > 1){
fflush(int_db.config->log_fptr);
last_flush = now;
}
2014-05-07 22:27:00 +00:00
}
if(log_destinations & MQTT3_LOG_SYSLOG){
#ifndef WIN32
syslog(syslog_priority, "%s", s);
#else
sp = (char *)s;
ReportEvent(syslog_h, syslog_priority, 0, 0, NULL, 1, 0, &sp, NULL);
#endif
}
if(log_destinations & MQTT3_LOG_TOPIC && priority != MOSQ_LOG_DEBUG){
if(int_db.config && int_db.config->log_timestamp){
len += 30;
st = mosquitto__malloc(len*sizeof(char));
2014-05-07 22:27:00 +00:00
if(!st){
mosquitto__free(s);
2014-05-07 22:27:00 +00:00
return MOSQ_ERR_NOMEM;
}
snprintf(st, len, "%d: %s", (int)now, s);
mqtt3_db_messages_easy_queue(&int_db, NULL, topic, 2, strlen(st), st, 0);
mosquitto__free(st);
2014-05-07 22:27:00 +00:00
}else{
mqtt3_db_messages_easy_queue(&int_db, NULL, topic, 2, strlen(s), s, 0);
}
}
mosquitto__free(s);
2014-05-07 22:27:00 +00:00
}
return MOSQ_ERR_SUCCESS;
}
int mosquitto__log_printf(struct mosquitto *mosq, int priority, const char *fmt, ...)
{
va_list va;
int rc;
va_start(va, fmt);
rc = mosquitto__log_vprintf(mosq, priority, fmt, va);
va_end(va);
return rc;
}
void mosquitto_log_printf(int level, const char *fmt, ...)
{
va_list va;
va_start(va, fmt);
mosquitto__log_vprintf(NULL, level, fmt, va);
va_end(va);
}