0
votes

I'm hooking printf-like function that is defined like this:

int Con_Printf(const char *format, ...)

I want to check if a given string is within the arguments or in the final formatted string and if is there, then replace it with another string, but I have the following code to pass the arguments to the original function:

va_list args;
char *parg;

va_start(args, format);
vasprintf(&parg, format, args);
va_end(args);

(*conprint)("%s", parg);
free(parg);

being (*conprint) the original Con_Printf function.

How can I view the string with format applied (i.e arguments replaced into placeholders) to replace what I need and not just pass through all the arguments?

Example: The program calls Con_Printf("%s %s", "foo", "bar"), I want to know in my Con_Printf hook if "bar" is within the arguments, but I don't know how many arguments are there because of the ", ...)" definition of Con_Printf.

If "bar" is found within the arguments, then replace it for "baz" and forward a modified call (*conprint)("%s %s", "foo", "baz") (replaced bar with baz). (*conprint)("foo baz") would do the trick too.

Thanks!

3
You should initialize parg=NULL;. BTW, your question is unclear, so edit it. Please give an example of expected behavior. - Basile Starynkevitch
what exactly do you mean by view the string after formatting? - Sourav Ghosh
edited to add more information, @SouravGhosh, I meant to be able to manipulate the string after format is applied. - Rodrigo

3 Answers

0
votes

I think, what you want is va_arg(). Check the man page here. Instead of directly using vasprintf(), you may want to

  1. take out one argument at a time
  2. perform required checks and operations
  3. then put them together for the final conprint.

from the manual page, the historic setup is:

#include <varargs.h>

void foo(va_alist)
    va_dcl
{
    va_list ap;

   va_start(ap);
    while (...) {
        ...
        x = va_arg(ap, type);
        ...
    }
    va_end(ap);
}

You need to choose the type based on the supplied format specifier

0
votes

Well, I think I missed the fact that the string part should contain the already formatted text, so I could directly do string manipulation on there to replace the needle.

So, my code finally ended like this:

va_list args;
char *parg;

va_start(args, format);
vasprintf(&parg, format, args);
va_end(args);

char* replacedstr;
replacedstr =  str_replace(parg, "bar", "baz");
(*conprint)("%s", replacedstr); 
free(parg);

Being str_replace a nice function that I've found somewhere (I've never coded in C, just doing experiments).

-1
votes
static (*__cdecl)F_HOOK *edit_f(&printf, sizeof(printf))
{
    __cdecl _:printf
    {
    /* .. code before executing printf stuff.. */
    }
}