My code is:
va_list args;
va_start(args, format);
vsyslog(severity, format, args);
va_end(args);
I want to add extra information before sending message to syslog server. I mean before vsyslog the extra information should add at the begining of string that send with vsyslog. How can I do this? or maybe I shoul ask is it possible? I hope I could explain my problem obviously.
The solution that I used in my code is:
va_list args;
va_start(args, format);
char *new_format = NULL;
asprintf(&new_format, "%s, %s", my_string, format);
vsyslog(severity, new_format, args);
free(new_format);
va_end(args);
Related
I am looking to make a small logger to be used like this:
logger log;
const char* text = "World";
log.write("Hello %s", text);
log.write("Step %d", 1);
This is my code, which doesn't work correctly:
class logger
{
public:
void write(const char* msg, ...)
{
FILE* file = fopen("c:/test.txt", "a");
if(file != NULL)
{
va_list args;
va_start(args, msg);
fprintf(file, "%s\n", msg, args);
va_end(args);
fclose(file);
}
}
};
This is what I get:
Hello %s
Step %d
I never used varargs before so I am not sure if I am using it correctly.
You're thinking that C behaves in a manner similar to Java or Python or other languages that can "splat" an array argument to a function that accepts varargs, but C isn't that sophisticated. When you pass args to fprintf, C literally pushes the value of args (a variable of type va_list) onto the stack. What you need instead is to push the contents of args onto the stack.
Or, instead, you could use a function that accepts a va_list as a parameter. That function is vprintf (and friends vsprintf, vfprintf, etc.).
You have another issue, which is that you're fprintf-ing the caller's "msg" parameter using "%s" but then apparently expecting fprintf to recursively use the result as a format string and fprintf the args too. That's not going to work. Instead just use the caller's msg as the format string.
va_list args;
va_start(args, msg);
vfprintf(file, msg, args);
fputc('\n', file);
va_end(args);
I am coding under Arduino and I would like to develop serial print formatting function, so I am trying to use sprintf of unknown sized buffer. Basically, we can avoid talking about Arduino and its serial output and consider writing text to a buffer and then printing it by using printf. I've tried this one:
#include <stdio.h>
#include <stdarg.h>
void printf0( const char* format, ... ) {
va_list args;
va_start(args, format);
vprintf(format, args);
va_end( args );
}
void printf1(const char* format,...) {
va_list args;
va_start(args, format);
char buf[vsnprintf(NULL, 0, format, args)];
sprintf(buf, format, args);
printf(buf);
va_end(args);
}
int main()
{
printf0("Hello, %d!\n", 15);
printf1("Hello, %d!\n", 15);
return 0;
}
printf0 function is an accurate example I found here. My tries is function printf1, which produces unpredictable number. Example output of the above programme is:
Hello, 15!
Hello, 860799736!
args is a va_list, so you cannot call sprintf with it. You have to use vsprintf or vsnprintf:
sprintf(buf, format, args);
should be
vsnprintf(buf, sizeof buf, format, args);
Also you should add 1 to the size of buf for the 0-terminator of the string:
char buf[vsnprintf(NULL, 0, format, args) + 1];
It seems that the first call to vsnprintf changes args, so you have to add
va_end(args);
va_start(args, format);
between the 2 calls:
http://ideone.com/5YI4Or
It seems that the first call to vsnprintf changes args, but you should not call va_start twice. You should use va_copy instead, so add
va_list args2;
va_copy(args2, args);
after initializing args. Also do not forget to call va_end(args2); too:
http://ideone.com/loTRNL
Link to the va_copy man page: https://linux.die.net/man/3/va_copy
I have function Log that logs variable length arguments. Unfortunately this function logs just first element. What is wrong?
Log(INFO,"aaa","bbb","ccc");
void Log(int level, char const * fmt, ...)
{
int len = 4096;
char buffer[len];
int ret;
va_list args;
va_start(args, fmt);
ret = vsnprintf(buffer, len, fmt, args);
va_end(args);
FILE *fOut;
fOut = fopen(nvLog_File, "at");
if(fOut)
{
fprintf(fOut, "%s\n",buffer);//,
printf("%s\n",buffer);
fclose(fOut);
} else fprintf(stderr, "can't open file %s", nvLog_File);
}
Your logging function works in a similar way to printf(). The first argument after log level should be formatting string, according to which the rest of arguments is interpreted. In order to print three strings, you should use log(INFO, "%s%s%s", "aaa", "bbb", "ccc");
The first string argument is the format. You need to specify where/how to format the other arguments. Try something like this:
Log(INFO, "aaa %s %s", "bbb", "ccc");
You should look at a reference for printf-style functions (http://www.cplusplus.com/reference/cstdio/printf/, for example).
According to this
Log(INFO,"aaa","bbb","ccc");
You pass in "aaa" as the format string, so when you forward it to printf you should see precisley that in your log. Everything else is ignored, as you are not making use of it.
I am trying to write a function which will take a priority level and a variable amount of strings as arguments to log information in an application.
The function looks something like this so far:
int _logf(int priority, char *fmt, ...)
{
if (log.priority >= priority) {
syslog(priority, "LOG:%s", fmt);
}
/* stderr and syslog */
}
log.priority is an int set at run time which could be LOG_INFO / LOG_DEBUG / LOG_ERR
and in use:
_logf(LOG_INFO, "Starting app version %s", "1.0");
Is this an acceptable way to send log messages to syslog?
This won't work as you do not involve the variable number of parameters possibly passed into your function.
On how to do this you might take a look a the following example using vsyslog():
#include <syslog.h>
#include <stdarg.h>
...
int _logf(int priority, const char * fmt, ...)
{
if (log.priority >= priority)
{
va_list ap;
va_start(ap, fmt);
vsyslog(priority, fmt, ap);
va_end(ap);
}
}
Then call it for example like so:
_logf(LOG_INFO, "LOG %s:%d (%s) - %s", __FILE__, __LINE__, __func__, "Just some info.");
Update:
To additionally log to stderr you might like to look ath function vfprintf().
void foo(int fmt, ...)
{
}
//I hook foo
static void (*original_foo)(int fmt, ...);
void replaced_foo(int fmt, ...)
{
printf("Hooking");
va_list args;
va_start(args, fmt);
//do something
va_end(args);
//But I want to call the original_foo function,
//I do not know how to invoke it ...
}
//Hook Function not include ...
Hook(foo, replaced_foo, (void **)&original_foo);
If you have a corresponding original_foo_v() which takes a va_args, you are lucky: you can use that.
If you don't (such as if you use DbgPrintf() or LStrPrintf() for interfacing with LabVIEW), you'll have to craft something on your own.
Essentially, you'll have to
examine the va_list you get,
find its stack frame by walking along the stack,
allocate as much memory on the stack as you need, assuming that you need the whole area between where the va_list points to and the next stack frame,
calling the non-va-aware function.
Of course, you'll have to do this for each and every platform you intend to support...
Good luck and have fun.