A lot of times people do zany things and try and reinvent wheels when it
comes to programming. Sometimes this is good: when learning, when trying
to improve state of the art, or when trying to simplify when only
Two-Ton solutions are available.

For a current daemon project I need good, fast, thread-safe logging.
syslog fits the bill to a tee and using anything else would be
downright foolish -- akin to implementing my own relational database.
There's one caveat. For development and debugging, I'd like to not
fork/daemonize and instead output messages to stdout. Some
implementations of syslog() define LOG_PERROR, but this is not in
POSIX.1-2008 and it also logs to both stderr and wherever the syslog
sink is set. That may not be desired.

So, the goals here are: continue to use syslog() for the normal case
as it is awesome, but allow console output in a portable way. Non-goals
were using something asinine like a reimplementation of Log4Bloat or
other large attempt at thread-safe logging from scratch.

Using function pointers, we can get a close approximation of an
Interface or Virtual Function of Object Oriented languages:

void(*LOG)(int,constchar*,...);int(*LOG_setmask)(int);

These are the same parameters that POSIX syslog() and setlogmask()
take. Now, at runtime, if we desire to use the the "real" syslog:

LOG=&syslog;LOG_setmask=&setlogmask;

If we wish to instead log to console, a little more work is in order.
Essentially, we need to define a console logging function "inheriting"
the syslog() "method signature" (or arguments for non-OO types).

/* In a header somewhere */voidlog_console(intpriority,constchar*format,...);intlog_console_setlogmask(intmask);

In about 60 lines of code we got the desired functionality by slightly
extending rather than reinventing things or pulling in a large external
dependency. If C++ is your cup of tea, it is left as a trivial
reimplementation where you can store the console logmask as a private
class variable.

Some notes:

You should still call openlog() at the beginning of your program in
case syslog() is selected at runtime. Likewise, you should still
call closelog() at exit.

It's left as a trivial exercise to the reader to define another
function to do logging to both stdout and, using vsyslog(), the
syslog. This implements LOG_PERROR in a portable way.

I chose stdout because it is line buffered by default. If you use
stderr, you should combine the loglevel, format, and newline with
sprintf before calling vprintf on the variable arglist to
prevent jumbled messages.

Of course, make sure you are cognizant that the format string is
passed in and do not allow any user-supplied format strings as
usual.