I have a linux application running on my desk top, and I wanted to redirect the syslog() calls to printf() calls.
Note: I do not want to replace the calls, just redirect
So I wrote some code to do this:
#ifndef EMBED
#define syslog(level, stuff) printf("SYSLOG: %s\n", stuff)
#endif
Works great in the one file where I was using it. I moved this to a new file and got an error:
error: macro "syslog" passed 3 arguments, but takes just 2
I know the error is because the calls in the new file are mixed, some are using 2 arguments to syslog, some are using 3. I also know I need to somehow redirect this via variable argument lists, but how exactly do I do this? I haven’t gotten it working yet…
As I understand it, syslog() and printf() should be:
void syslog(int priority, const char *format, ...)
int printf(const char *format, ...)
So I tried:
#define ERR 3
#ifndef EMBED // This is not defined in my env, btw
#define syslog(pri, fmt, ...) printf(fmt, ...)
#endif
...
void main() {
...
syslog(ERR, "test");
but that gives the error:
error: expected expression before ‘...’ token
Suggestions on how this macro should look/be used?
GCC has an extension in this area, but the most portable way of handling it is:
The priority is mandatory, but is ignored by the macro expansion. The rest of the arguments (the mandatory format plus optional following arguments) are in the
__VA_ARGS__used in the argument list toprintf(). This will be OK whether the format string is a constant (literal) or a variable.If you want to tag the output as being for the surrogate of
syslog(), I’d call a function other thanprintf()to do the job:or even
These would be declared as:
or:
The implementation is a straight-forward application of the macros in
<stdarg.h>plus thev*printf()functions:You can add timestamps and whatever else you like; you can also rather easily arrange for the output to go to a file instead of standard output; you can also arrange for it to be turned on or off inside the function. So, on average, I would replace
syslog()with a surrogate that allows you to tune your codes use of the facilities.In fact, since you’ve uncovered a requirement to change the behaviour of logging, I would suggest that instead of using
syslog()directly in your code, you should use your own function (for example, thesyslog_printf(), but possibly under a different name) in your code, and have various implementations of that function available to you. The only downside to doing so is that calling the realsyslog()is now harder — there isn’t avsyslog()AFAIK. So, the basic call tosyslog()would be done by formatting the string insyslog_printf()usingvsnprintf()(orvasprintf()if that’s available to you and memory exhaustion isn’t a likely problem), and then callingsyslog()with the preformatted string (syslog(priority, "%s", buffer);). Of course, you’d also want the priority passed to the surrogate function for relay tosyslog().