2014-05-07 22:27:00 +00:00
|
|
|
/*
|
2015-04-19 21:10:59 +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
|
2015-04-29 20:37:47 +00:00
|
|
|
#include "config.h"
|
2014-05-07 22:27:00 +00:00
|
|
|
#endif
|
|
|
|
|
2015-04-29 20:37:47 +00:00
|
|
|
#include "mosquitto_broker.h"
|
|
|
|
#include "memory_mosq.h"
|
|
|
|
#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){
|
2015-02-08 22:06:11 +00:00
|
|
|
if(drop_privileges(config, true)){
|
|
|
|
return 1;
|
|
|
|
}
|
2015-04-19 21:10:59 +00:00
|
|
|
config->log_fptr = mosquitto__fopen(config->log_file, "at");
|
2015-02-05 22:44:38 +00:00
|
|
|
if(!config->log_fptr){
|
2015-04-19 21:10:59 +00:00
|
|
|
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;
|
|
|
|
}
|
2015-02-08 22:06:11 +00:00
|
|
|
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);
|
2015-02-08 22:06:11 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2015-04-19 21:10:59 +00:00
|
|
|
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);
|
2015-02-05 22:29:49 +00:00
|
|
|
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;
|
2015-04-19 21:10:59 +00:00
|
|
|
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);
|
|
|
|
}
|
2015-02-05 22:29:49 +00:00
|
|
|
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;
|
2015-04-19 21:10:59 +00:00
|
|
|
st = mosquitto__malloc(len*sizeof(char));
|
2014-05-07 22:27:00 +00:00
|
|
|
if(!st){
|
2015-04-19 21:10:59 +00:00
|
|
|
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);
|
2015-04-19 21:10:59 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
2015-04-19 21:10:59 +00:00
|
|
|
mosquitto__free(s);
|
2014-05-07 22:27:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return MOSQ_ERR_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2015-04-19 21:10:59 +00:00
|
|
|
int mosquitto__log_printf(struct mosquitto *mosq, int priority, const char *fmt, ...)
|
2014-11-03 08:45:56 +00:00
|
|
|
{
|
|
|
|
va_list va;
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
va_start(va, fmt);
|
2015-04-19 21:10:59 +00:00
|
|
|
rc = mosquitto__log_vprintf(mosq, priority, fmt, va);
|
2014-11-03 08:45:56 +00:00
|
|
|
va_end(va);
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
void mosquitto_log_printf(int level, const char *fmt, ...)
|
|
|
|
{
|
|
|
|
va_list va;
|
|
|
|
|
|
|
|
va_start(va, fmt);
|
2015-04-19 21:10:59 +00:00
|
|
|
mosquitto__log_vprintf(NULL, level, fmt, va);
|
2014-11-03 08:45:56 +00:00
|
|
|
va_end(va);
|
|
|
|
}
|
|
|
|
|