[英]How can I map linux syslog to printf in C
我在桌面上运行了一个linux应用程序,我想将syslog()调用重定向到printf()调用。
注:我不想更换电话,只是重定向
所以我写了一些代码来做到这一点:
#ifndef EMBED
#define syslog(level, stuff) printf("SYSLOG: %s\n", stuff)
#endif
在我使用它的一个文件中工作得很好。 我将其移动到一个新文件并收到错误:
error: macro "syslog" passed 3 arguments, but takes just 2
我知道错误是因为新文件中的调用是混合的,有些是使用2个参数连接到syslog,有些是使用3.我也知道我需要以某种方式通过变量参数列表重定向,但我该怎么做? 我还没有工作呢......
据我了解,syslog()和printf()应该是:
void syslog(int priority, const char *format, ...)
int printf(const char *format, ...)
所以我尝试过:
#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");
但是这给出了错误:
error: expected expression before ‘...’ token
关于如何使用这个宏的建议?
GCC在这方面有一个扩展,但最便携的处理方式是:
#define syslog(priority, ...) printf(__VA_ARGS__)
优先级是强制性的,但宏扩展会忽略。 其余参数(强制格式加上可选的后续参数)位于printf()
的参数列表中使用的__VA_ARGS__
中。 无论格式字符串是常量(文字)还是变量,都可以。
如果你想将输出标记为syslog()
的代理,我会调用printf()
以外的printf()
来完成这项工作:
#define syslog(priority, ...) syslog_print(__VA_ARGS__)
甚至
#define syslog(priority, ...) syslog_print(__FILE__, __LINE__, __func__, __VA_ARGS__)
这些将被声明为:
extern void syslog_printf(const char *fmt, ...);
要么:
extern void syslog_printf(const char *file, int line, const char *func,
const char *fmt, ...);
该实现是<stdarg.h>
加上v*printf()
函数的宏的直接应用:
void syslog_printf(const char *file, int line, const char *func,
const char *fmt, ...)
{
va_list args;
printf("SYSLOG:%s:%d:%s: ", file, line, func);
va_start(args, fmt);
vprintf(fmt, args);
va_end(args);
}
您可以添加时间戳以及您喜欢的任何其他内容; 你也可以很容易地安排输出转到文件而不是标准输出; 您也可以安排在功能内打开或关闭它。 因此,平均而言,我会将syslog()
替换为允许您调整代码使用设施的代理。
事实上,既然你已经发现了改变日志记录行为的要求,我建议你不要直接在代码中使用syslog()
,而应该使用你自己的函数(例如, syslog_printf()
,但可能在代码中的不同名称,并且可以使用该功能的各种实现。 这样做的唯一缺点是调用真正的syslog()
现在更难 - 没有vsyslog()
AFAIK。 因此,对syslog()
的基本调用将通过使用vsnprintf()
(或vasprintf()
格式化syslog_printf()
的字符串来完成,如果您可以使用它并且内存耗尽不是可能的问题),然后调用syslog()
使用预格式化的字符串( syslog(priority, "%s", buffer);
)。 当然,您还希望将优先级传递给代理函数以进行中继到syslog()
。
fmt
字符串应包含自己的格式说明符,这些说明符用可变参数填充。 首先,您可以简单地忽略实际参数,只打印格式化字符串。 你需要一个可变的宏:
#define syslog(level, fmt, ...) printf("SYSLOG: %s\n", fmt)
其次,如果您愿意承担巨大的风险并期望用户提供格式字符串作为文字而不是变量,您可以连接自己的字符串:
#define syslog(level, fmt, ...) printf("SYSLOG[%d] " fmt, level, ##__VA_ARGS__)
这适用于syslog(1, "Hello");
,但不适用于syslog(1, str);
。
如果您不想依赖于可变参数宏(C99功能),您也可以这样做:
#define syslog my_syslog
static inline int my_syslog(int prio, const char *fmt, ...)
{
int r;
va_list ap;
va_start(ap, fmt);
r = vprintf(fmt, ap);
va_end(ap);
return r;
}
或类似的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.