* History
* ===========================================================
* Version Date Author Description
* ===========================================================
* 0.1 10-MAR-11 Seree R. Initial
*/
#ifndef _xsyslog_h_
#define _xsyslog_h_
#include <map>
#include <string>
#include <pthread.h>
/*
* xsyslog is implemented by singleton pattern
*/
typedef std::map<std::string, int> str2int_t;
class xsyslog {
private:
/*
* Not allow new object by constructor, copy constructor, and also assignment operator.
*/
xsyslog();
xsyslog(const xsyslog&);
xsyslog operator=(const xsyslog&);
public:
/*
* Create an instance of this object
*/
static xsyslog *instance();
virtual ~xsyslog();
public:
/*
* NAME:
* write - write a message to system log
* SYNOPSIS:
* void write(const char *format, ...);
* static void write(const char *id, int facility, int level, const char *format, ...);
* DESCRIPTION:
* The write() function sends a message to syslogd, which,
* depending on the configuration of /etc/syslog.conf
* RETURN VALUES:
* None
* ERRORS:
* None
* EXAMPLES:
* xsyslog *log = xsyslog::instance();
* log->id("my application");
* log->facility("LOG_LOCAL3");
* log->level("LOG_INFO");
* log->write("This is logged by pid(%d)", getpid());
*/
void write(const char *format, ...);
static void write(const char *id, int facility, int level, const char *format, ...);
/*
* NAME:
* facility - get or set a facility of the message to system log
* SYNOPSIS:
* int facility() const; - get
* int facility(int facility); - set by integer
* int facility(const char *facility); - set by string
* DESCRIPTION:
* The facility() function gets or sets the facility of the message to system log
* RETURN VALUES:
* The current facility or old facility before setting the new facility.
* See also facility in syslog(3C). Otherwise, -1 if facility string is to be set,
* it is not correct.
* ERRORS:
* None
* EXAMPLES:
* int old_facility = xsyslog::instance()->facility("LOG_LOCAL3");
*/
int facility() const { return facility_; }
int facility(int facility);
int facility(const char *facility);
/*
* NAME:
* level - get or set a level of the message to system log
* SYNOPSIS:
* int level() const; - get
* int level(int level); - set by integer
* int level(const char *level); - set by string
* DESCRIPTION:
* The level() function gets or sets the level of the message to system log
* RETURN VALUES:
* The current level or old level before setting the new level.
* See also level in syslog(3C). Otherwise, -1 if level string is to be set,
* it is not correct.
* ERRORS:
* None
* EXAMPLES:
* int old_level = xsyslog::instance()->level("LOG_INFO");
*/
int level() const { return level_; }
int level(int level);
int level(const char *level);
/*
* NAME:
* id - get or set an identifier of the message to system log
* SYNOPSIS:
* const char *id() const; - get
* const char *id(const char *id); - set
* DESCRIPTION:
* The id() function gets or sets the id of the message to system log
* RETURN VALUES:
* The current id or old id before setting the new id.
* See also id in syslog(3C). Otherwise, -1 if id string is to be set,
* it is not correct.
* ERRORS:
* None
* EXAMPLES:
* int old_level = xsyslog::instance()->id("my application");
*/
const char *id() const;
const char *id(const char *id);
private:
std::string id_;
int facility_;
int level_;
pthread_mutex_t mutex_write_;
pthread_mutex_t mutex_id_;
pthread_mutex_t mutex_facility_;
pthread_mutex_t mutex_level_;
private:
static str2int_t map_facility_;
static str2int_t map_level_;
static xsyslog *instance_;
};
#endif // _xsyslog_h_
///////////////////////////////////////
/*
* History
* ===========================================================
* Version Date Author Description
* ===========================================================
* 0.1 10-MAR-11 Seree R. Initial
*/
#include "xsyslog.h"
#include <syslog.h>
#include <stdarg.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
using std::map;
using std::string;
xsyslog *xsyslog::instance_ = 0;
str2int_t xsyslog::map_facility_ = str2int_t();
str2int_t xsyslog::map_level_ = str2int_t();
xsyslog::xsyslog()
: id_("xsyslog"), facility_(LOG_LOCAL0), level_(LOG_INFO)
{
// mutex
pthread_mutex_init(&mutex_write_, 0);
pthread_mutex_init(&mutex_id_, 0);
pthread_mutex_init(&mutex_facility_, 0);
pthread_mutex_init(&mutex_level_, 0);
}
xsyslog::~xsyslog() {
pthread_mutex_destroy(&mutex_write_);
pthread_mutex_destroy(&mutex_id_);
pthread_mutex_destroy(&mutex_facility_);
pthread_mutex_destroy(&mutex_level_);
}
/*
Facility:
=========
LOG_AUTH The authorization system: login(1), su(1), getty(8), etc.
LOG_CRON The cron daemon: cron(8).
LOG_DAEMON System daemons, such as routed(8), that are not provided for explicitly by other facilities.
LOG_KERN Messages generated by the kernel. These cannot be generated by any user processes.
LOG_LPR The line printer spooling system: lpr(1), lpc(8), lpd(8), etc.
LOG_MAIL The mail system.
LOG_NEWS The network news system.
LOG_SYSLOG Messages generated internally by syslogd(8).
LOG_USER Messages generated by random user processes. This is the default facility identifier if none is specified.
LOG_UUCP The uucp system.
LOG_LOCAL0 Reserved for local use. Similarly for LOG_LOCAL1 through LOG_LOCAL7.
Level:
======
LOG_EMERG A panic condition. This is normally broadcast to all users.
LOG_ALERT A condition that should be corrected immediately, such as a corrupted system database.
LOG_CRIT Critical conditions, e.g., hard device errors.
LOG_ERR Errors.
LOG_WARNING Warning messages.
LOG_NOTICE Conditions that are not error conditions, but should possibly be handled specially.
LOG_INFO Informational messages.
LOG_DEBUG Messages that contain information normally of use only when debugging a program.
*/
xsyslog *xsyslog::instance() {
if(!instance_) {
instance_ = new xsyslog();
// setup facility
map_facility_["LOG_AUTH"] = LOG_AUTH;
map_facility_["LOG_CRON"] = LOG_CRON;
map_facility_["LOG_DAEMON"] = LOG_DAEMON;
map_facility_["LOG_KERN"] = LOG_KERN;
map_facility_["LOG_LPR"] = LOG_LPR;
map_facility_["LOG_MAIL"] = LOG_MAIL;
map_facility_["LOG_NEWS"] = LOG_NEWS;
map_facility_["LOG_SYSLOG"] = LOG_SYSLOG;
map_facility_["LOG_USER"] = LOG_USER;
map_facility_["LOG_UUCP"] = LOG_UUCP;
map_facility_["LOG_LOCAL0"] = LOG_LOCAL0;
map_facility_["LOG_LOCAL1"] = LOG_LOCAL1;
map_facility_["LOG_LOCAL2"] = LOG_LOCAL2;
map_facility_["LOG_LOCAL3"] = LOG_LOCAL3;
map_facility_["LOG_LOCAL4"] = LOG_LOCAL4;
map_facility_["LOG_LOCAL5"] = LOG_LOCAL5;
map_facility_["LOG_LOCAL6"] = LOG_LOCAL6;
map_facility_["LOG_LOCAL7"] = LOG_LOCAL7;
// setup level
map_level_["LOG_EMERG"] = LOG_EMERG;
map_level_["LOG_ALERT"] = LOG_ALERT;
map_level_["LOG_CRIT"] = LOG_CRIT;
map_level_["LOG_ERR"] = LOG_ERR;
map_level_["LOG_WARNING"] = LOG_WARNING;
map_level_["LOG_NOTICE"] = LOG_NOTICE;
map_level_["LOG_INFO"] = LOG_INFO;
map_level_["LOG_DEBUG"] = LOG_DEBUG;
}
return instance_;
}
void xsyslog::write(const char *format, ...) {
// format string to log
char sz[1];
va_list args;
va_start(args, format);
int len = vsnprintf(sz, 1, format, args);
char *buffer = (char *)malloc(len+1);
vsnprintf(buffer, len+1, format, args);
va_end(args);
// write the syslog now
pthread_mutex_lock(&mutex_write_);
openlog(id_.c_str(), LOG_PID|LOG_NDELAY, facility_);
syslog(level_, "%s", buffer);
closelog();
pthread_mutex_unlock(&mutex_write_);
// clean up memory
free(buffer);
}
void xsyslog::write(const char *id, int facility, int level, const char *format, ...) {
// format string to log
va_list args;
va_start(args, format);
char sz[1];
int len = vsnprintf(sz, 1, format, args);
char *buffer = (char *)malloc(len+1);
vsnprintf(buffer, len+1, format, args);
va_end(args);
// write the syslog now
openlog(id, LOG_PID|LOG_NDELAY, facility);
syslog(level, "%s", buffer);
closelog();
free(buffer);
}
const char *xsyslog::id() const {
return id_.c_str();
}
const char *xsyslog::id(const char *id) {
pthread_mutex_lock(&mutex_id_);
string old_id = id_;
id_ = id;
pthread_mutex_unlock(&mutex_id_);
return old_id.c_str();
}
int xsyslog::facility(const char *facility) {
str2int_t::iterator it = map_facility_.find(facility);
if(it != map_facility_.end()) {
pthread_mutex_lock(&mutex_facility_);
int old_facility = facility_;
facility_ = (*it).second;
pthread_mutex_unlock(&mutex_facility_);
return old_facility;
}
return -1;
}
int xsyslog::level(const char *level) {
str2int_t::iterator it = map_level_.find(level);
if(it != map_level_.end()) {
pthread_mutex_lock(&mutex_level_);
int old_level = level_;
level_ = (*it).second;
pthread_mutex_unlock(&mutex_level_);
return old_level;
}
return -1;
}
int xsyslog::level(int level) {
pthread_mutex_lock(&mutex_level_);
int old_level = level_;
level_ = level;
pthread_mutex_unlock(&mutex_level_);
return old_level;
}
int xsyslog::facility(int facility) {
pthread_mutex_lock(&mutex_facility_);
int old_facility = facility_;
facility_ = facility;
pthread_mutex_unlock(&mutex_facility_);
return old_facility;
}
/////////////////////////////////////////
#include "xsyslog.h"
#include <stdio.h>
#include <syslog.h>
/*
edit /etc/syslog.conf
add facility.level and path as needed
touch the path if it does not exist
*/
int main(int argc, char *argv[]) {
if(argc != 5) {
fprintf(stderr, "usage: %s id facility level log_message\n", argv[0]);
fprintf(stderr, "example: %s \"myid\" \"LOG_LOCAL0\" \"LOG_INFO\" \"TEST MESSAGE\"\n", argv[0]);
return 1;
}
xsyslog *log = xsyslog::instance();
// log->id("EMT_TSA_3.5.2");
// log->facility("LOG_LOCAL3");
// log->level("LOG_INFO");
log->id(argv[1]);
log->facility(argv[2]);
log->level(argv[3]);
log->write("%s", argv[4]);
xsyslog::write(argv[1], LOG_LOCAL0, LOG_NOTICE, "%s with static write function", argv[4]);
return 0;
}