How to call a varargs function via dbus, like printf?
The server is written in C, the client is written in Python.
My questions are how to write the XML spec file? And how to write my GObject?
Thanks in advance.
[I use DBus-GLib.]
There is no way to call a variadic function programmatically with varying number and type of arguments. You could use the corresponding "v" functions (vprintf etc.) but there's no way to make the va_list to pass to them from foreign code and pass it over DBus.
In any case you really need to rethink your design. It's unsafe to call printf with a format string that's not 100% controlled by your program. Passing a client-provided format string is a formula for disaster, because printf invokes undefined behavior if the format string does not match the arguments. In nearly all real-world situations, this will mean privilege elevation vulns!
Related
Let's say I have a function:
int foo (int A, char B){...}
One of the features I want to implement is the capability for the user to call any function on the application through the Linux terminal. So as an input for the software, in the terminal they type something like:
foo 2 'a'
Then my application parses that, and using the symbol tables it is able to find the address for foo(), as well as the type for all its parameters.
However, I'm not sure how I would pass the parameters to the function when calling it, since I can have hundreds of different parameters types combination depending on the function called.
Any hint how that could be achieved without having hundreds of nested if statements to cast the parameters to the correct types before calling the functions?
That functionality is similar to what GDB has, where you can do call foo(2,'a') and GDB calls that function to you.
There are two approaches to this. If what you described is all you want to do, then you can use the dyncall library so that you dont have to worry about platform/compiler-specific calling semantics yourself:
The dyncall library encapsulates architecture-, OS- and compiler-specific function call semantics in a virtual bind argument parameters from left to right and then call interface allowing programmers to call C functions in a completely dynamic manner. In other words, instead of calling a function directly, the dyncall library provides a mechanism to push the function parameters manually and to issue the call afterwards.
The other approach is, if you might want to do more: e.g. what if an argument cannot be created by a literal? What if the argument is the output of another function? Can you write f(123, g("a")) in your console? Can you write x=g("a"); f(x)? And if(cond) x="a" else x="b"; f(x) In this case you need to embed a scripting language like e.g. LUA.
If you compile your binary with debug information, you can extract it using libdwarf (https://www.prevanders.net/dwarf.html), so for every function you can get a list a parameters with types and you would know how to interpret user's input.
I've just discovered variadic functions in C and have defined one as a general notification typedef, that as well as a pointer to a text string can optionally have whatever arguments sent along with it- useful as a generic debug function for instance where I want all the output string manipulation in one place.
Since I want my C files to be as generic as possible I have static variables that contain pointers to possible callbacks in higher code, populated in an init call. Since the pointers may be null if higher code isn't interested, I'd normally have a local wrapper that only calls through the pointer if it's not null. But I'm having trouble figuring out how to forward this fuzzy thing represented by '...' and simply calling the function with '...' in the argument list gives a syntax error.
Is there any way to do this, or am I stuck with having a dummy local handler and having init set null callbacks to a pointer to that?
You can't pass on the variadic arguments. You have to fetch them into a va_list and pass this to the inner function.
Take a look at this Question at the C FAQ. It defines a variadic error function that wants to forward to printf. This is just your use case.
In the same FAQs, it is generally recommended to have a version taking va_list for every (or most) variadic functions
string.format("%q", foo_str) will format a string to add the appropriate escape chars to make it safe to read back into the Lua interpreter. How can I best use this function to format a Lua_Buffer from the C-API? More generally, how can I access the string.* functions from the C-API? I could use lua_pcall("string.format", ...), but curious if there is a more direct way.
The format function is defined as static in the lstrlib.c module, so AFAIK the only way to get to it is through the string table.
I suppose you could look at addquoted in lstrlib.c and adjust it for your use, but probably easier to just call string.format.
I am developing a custom LISP interpreter. It won't support defining functions like in LISP, instead all functions are mapped to C functions. When it sees an expression like,
(substr 'input '1 '1)
it knows to call internal substr function and return the result.
Now I am planning to implement a message function which supports basic formatting and writes the output to stdout. Something like,
(message "Hello, %s" name)
%s will be replaced with value in variable name.
Current plan is to directly pass the format and arguments to functions like printf. In that way, I can support all formats that printf supports. But problem comes with variable number of arguments. One way to do will be something like,
if(argcount == 1)
/* call printf with one arg */
else if(argcount == 2)
/* call printf with two arg */
....
This works, but I am wondering is there a better way to achieve this?
I doubt there is a way to do this. The reason is that the number of parameters to your lisp function is only known at runtime, but the number of arguments to a C function must be known at compile time.
This includes va_lists unless you want to hack at them in some kind of platform specific way.
The best you can really do is write a function in C which is capable of looping through the arguments one at a time and doing something with them. The only way I can see around this is to not only store a function pointer for each of your internal functions, but to also store a "calling convention" which will give information about whether it takes parameters in the ordinary way or whether it finishes with the equivalent of a va_list.
Functions like printf would have a wrapper, printf_wrapper, say, and you'd store a function pointer to the wrapper. This wrapper would accept the format string as an ordinary parameter, followed by a list or array of other parameters (roughly analogous to a va_list).
You might indicate that printf_wrapper finishes with a parameter that expects a list by specifying the calling conventions for the printf_wrapper function as "va_list_type", meaning that it takes the usual fixed parameters, and that all remaining parameters must be bundled up and supplied to it as a list.
Of course writing a printf_wrapper function which can split up and parse a format string into multiple format strings is a bit of work. Here's an example of where I did precisely this so that I could add my own custom format specifiers:
https://github.com/wbhart/bsdnt/blob/v0.26/helper.c
Have your C function take parameters somewhat like argc/argv. That is, take a parameter specifying the number of parameters, and then a pointer to a list of pointers for each parameter.
Slightly better than an if-else chain would be a switch.
switch(argcount){
case 1: printf(arg[0]); break;
case 2: printf(arg[0],arg[1]); break;
//etc.
}
I was wondering how I could do this. I'm mostly puzzled by the N arguments part:
printf("Hello, I'm %i years old and my mom is %i .",me.age(),mom.age());
I want to make a function that will take a formatted string like this and return a std string.
How is the N arguments part done?
printf is a variadic function; you can implement your own variadic functions using the facilities provided by <stdarg.h>.
In C++, you should avoid variadic functions wherever possible. They are quite limited in what types they can accept as arguments and they are not type safe. C++0x adds variadic templates to C++; once support for this feature is widespread, you'll be able to write type safe variadic functions.
In the meantime, it's best to use some other type safe method. Boost.Format, for example, overloads the % operator to perform formatting.